autofac

Reproducing Promise IoC in C#

Another diversion before getting back to actual Promise language syntax description, this time trying to reproduce the Promise IoC syntax in C#. Using generics gets us a good ways there, but we do have to use a static method on a class as the registrar giving us this syntax:

$#[Catalog].In(:foo).Use<DbCatalog>.ContextScoped;
// becomes
Context._<ICatalog>().In("foo").Use<DbCatalog>().ContextScoped();

Not too bad, but certainly more syntax noise. Using a method named _ is rather arbitrary, i know, but it at least kept it more concise. Implementation-wise there's a lot of assumptions here: This approach forces the use of interfaces for Promise types, which can't be enforced by generic constraints. It would also be fairly simple to pre-initialize the Context with registrations that look for all interfaces IFoo and then find the implementor Foo and register that as the default map, mimicking the default Promise behavior by naming convention instead of Type/Class name shadowing.

Next up, instance resolution:

var foo = Foo();
// becomes
var foo = Context.Get<IFoo>();

This is where the appeal of the syntax falls down, imho. At this point you might as well just go to constructor injection, as with normal IoC. Although you do need that syntax for just plain inline resolution.

And the whole thing uses a static class, so that seems rather hardcoded. Well, at least that part we can take care of: If we follow the Promise assumption that a context is always bound to a thread, we can use [ThreadStatic] to chain context hierarchies together so that what looks like a static accessor is really just a wrapper around the context thread state. Given the following Promise syntax:

context(:inner) {
  $#[Catalog].In(:inner).ContextScoped;
  $#[Cart].ContextScoped;

  var catalogA = Catalog();
  var cartA = Cart();

  context {
    var catalogB = Catalog(); // same instance as catalogA
    var catalogC = Catalog(); // same instance as A and B
    var cartB = Cart(); // different instance from cartA
    var cartC = Cart(); // same instance as cartB
  }
}

we can write it in C# like this:

using(new Context("inner")) {
  Context._<ICatalog>().In("inner").ContextScoped();
  Context._<ICart>().ContextScoped();

  var catalogA = Context.Get<ICatalog>();
  var cartA = Context.Get<ICart>();

  using(new Context()) {
    var catalogB = Context.Get<ICatalog>(); // same instance as catalogA
    var catalogC = Context.Get<ICatalog>(); // same instance as A and B
    var cartB = Context.Get<ICart>(); // different instance from cartA
    var cartC = Context.Get<ICart>(); // same instance as cartB
  }
}

This works because Context is IDisposable. When we new up an instance, it takes the current threadstatic and stores it as it's parent and sets itself as the current. Once we leave the using() block, Dispose() is called, at which time, we set the current context's parent back as current, allowing us to build up and un-roll the context hierarchy:

public class Context : IDisposable {

  ...

  [ThreadStatic]
  private static Context _current;

  private Context _parent;

  public Context() {
    if(_current != null) {
      _parent = _current;
    }
    _current = this;
  }

  public void Dispose() {
    _current = _parent;
  }
}

I'm currently playing around with this syntax a bit more and using Autofac inside the Context to do the heavy lifting. If I find the syntax more convenient than plain Autofac, i'll post the code on github.

By arne on | .net, geek | A comment?
Tags: , , ,

Setting up mocks for an inner autofac container

This is definitely an edge case testing scenario, so i don’t know how useful this utility class is in general, but i thought it was kinda fun deferred execution stuff, so why not post it?

Here’s my scenario. I’ve built some Dream REST services that i’ve set up to create an inner Autofac container per request to create per request instances of objects — things like NHibernate ISession and other disposable resources that only make sense in a per request context.

Now i’m writing my unit tests around these services, and need to provide mocks for these inner container created objects. I should also mention that to test the services, i am firing up a DreamHost, since the services can only be tested in the context of the full pipeline. Yeah, i know, smells a bit functional, but that’s what I have to work with right now. And i need these objects to be ContainerScoped (i.e. per inner container singletons), so that multiple Resolve‘s return the same instance, but still return different instances on multiple requests. Ok, ok, i know the tests are doing too much… Like i said, this is an edge case. It’s not strictly a unit test, but i still want coverage on this code. Getting around this would require refactoring of code that’s not part of my project, so there you go.

What I want to do is set up the mock for the inner container instance on creation, which doesn’t happen until i’ve handed over execution control to the Act part of the test. This lead me to create a factory that provides a hook for setting up the mock on creation of the mock:

public class DelegatedMoqFactory<T> where T : class
{
 private Action<Mock<T>, IContext> setupCallback;
 private Mock<T> mock;

 public Mock<T> CurrentMock { get { return mock; } }

 public T CreateInstance(IContext container)
 {
  mock = new Mock<T>();
  if (setupCallback != null)
  {
   setupCallback(mock, container);
  }
  return mock.Object;
 }

 public void OnResolve(Action<Mock<T>, IContext> setupCallback)
 {
  this.setupCallback = setupCallback;
 }
}

A sample autofac wire-up looks like this:

builder.RegisterGeneric(typeof(DelegatedMoqFactory<>));
builder.Register(c => c.Resolve<DelegatedMoqFactory<IAuthService>>().CreateInstance(c))
    .ContainerScoped();

With a test setup of the IAuthService being done like this:

container.Resolve<DelegatedMoqFactory<IAuthService>>()
    .OnResolve(m => m.Setup(x =>
        x.AuthenticateAndGetAccountId("authtoken")).Returns(1234);

The open generic of DelegateMoqFactory is registered with default scope, since i want it to exist outside the inner scope, so that i can resolve it to wire up my expectations for the mock. Then on the first access for IAuthService inside the inner scope, the DelegateMoqFactory creates the mock and calls my OnResolve callback to set up the mock.

The reason there is also a CurrentMock accessor is so that I can do verification on the mock after the inner container has gone out of scope, like this:

container.Resolve<DelegatedMoqFactory<IAuthService>>()
    .CurrentMock.Verify(x =>
        x.CreateAuthToken(It.IsAny<IAccount>()), Times.Never());

This class should be useful whenever you are testing some code that internally creates an inner container and scoping the objects usually created under ContainerScope as default scope doesn’t work (likely because there’s multiple inner containers). We still get per inner container instances, but get to wire them up with deferred setups that don’t come into play until the mocks are actually pulled from the inner container.

By arne on | .net | A comment?
Tags: , , ,

Using TDD to learn new code

When I pick up a new framework or library, there’s usually that learning curve where I get familiar with its API, find what works, what doesn’t work, etc. One habit I’ve gotten into is that I create a TestFixture for everything i think i should be able to do and build a test for that assumption. The purpose of these tests is both to make sure the code does what I expect it to, but also to serve as a record of what I’ve already learned. If i later on wonder how some call would function, i first check my test signatures, to see if i’ve already tested that behavior. If there is an appropriate test, I immediately know what the behavior will be, plus i now have working sample code or how to do it.

For example, I was playing around with setting up Moq‘s through Autofac and wanted to come up with a registration that would give me a container scoped Moq object that i could set up before executing a particular test. The resulting test looked like this:

public interface IMockWithAccessor
{
 IMockAccessorValue Accessor { get; }
}
public interface IMockAccessorValue
{
 string Foo { get; }
}

[Test]
public void Create_nested_mock_so_it_can_be_altered_in_container_scope()
{
 var builder = new ContainerBuilder();
 builder.Register(c => new Mock<IMockAccessorValue>())
  .As<Mock<IMockAccessorValue>>().ContainerScoped();
 builder.Register(c => c.Resolve<Mock<IMockAccessorValue>>().Object)
  .As<IMockAccessorValue>().ContainerScoped();
 builder.Register(c =>
 {
  var mockBuilder = new Mock<IMockWithAccessor>();
  mockBuilder.Setup(x => x.Accessor)
                       .Returns(c.Resolve<IMockAccessorValue>());
  return mockBuilder.Object;
 }).As<IMockWithAccessor>().ContainerScoped();

 using (var container = builder.Build().CreateInnerContainer())
 {
  var mockAccessorBuilder = container
                     .Resolve<Mock<IMockAccessorValue>>();
  mockAccessorBuilder.Setup(x => x.Foo).Returns("bar");
  Assert.AreEqual("bar", container
                     .Resolve<IMockWithAccessor>().Accessor.Foo);
 }
}

Sometimes, of course, my expectations are not met and the code does not allow me to do what i set out to do. These test are even more valuable for future reference, as long as i make sure to rename the test to reflect the failed expectation, and alter the asserts to reflect the actual behavior.

I was trying to figure out parametrized component registrations in Autofac. The example showed it being used with FactoryScope. I wondered whether, in default (Singleton) scope, Autofac would use the parameters to create singletons per parameter set. My original test was named Parametrized_resolve_creates_different_singleton_per_parameter_Value. Well, it turned out that, no, autofac does not vary singletons, and parametrized registrations only make sense in FactoryScope. The final test looks like this:

public class ParametrizedSingleton { }
[Test]
public void Parametrized_resolve_without_factory_scope_is_always_a_singleton()
{
 var builder = new ContainerBuilder();
 builder.Register((c, p) => new ParametrizedSingleton());
 using (var container = builder.Build())
 {
  var foo1 = container.Resolve<ParametrizedSingleton>(
                     new NamedParameter("type", "foo"));
  var foo2 = container.Resolve<ParametrizedSingleton>(
                     new NamedParameter("type", "foo"));
  var bar1 = container.Resolve<ParametrizedSingleton>(
                     new NamedParameter("type", "bar"));
  Assert.AreSame(foo1, foo2);
  Assert.AreSame(foo1, bar1);
 }
}

I usually keep these test fixtures in a separate test project in my solution as permanent reference, as i continue to develop the main code. It’s proven useful a number of times when coming back to some old code and having to reacquaint myself with a third party bit of code.

By arne on | .net | A comment?
Tags: , ,