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.
Labels: autofac, lambda, moq, tdd
Moq rocks
Ok, so i'm not proud of it, but i've been a hold-out on mocking frameworks for a while. With the auto-gen of interfaces that resharper gives me, i'd just gotten pretty fast at rolling my own mocks. Once or twice a year, i'd dip my toe into a mocking framework, find its syntax frustrating and rather than get a good used to it, I'd soon find myself replacing
NotImplementedException in a stub for yet another custom Mock object.
My reasoning was that if i can roll my mocks just as fast as wiring up a mock, then why bother with the dependency. And I thought I wasn't really causing myself too much extra work.
In the meantime, I even wrote a simple Arrange/Act/Assert mocking harness for Dream, so i could better test REST services. So, it's not like i didn't believe in the benefits of mocking harnesses.
Well, for the last couple of weeks, I've been using Moq and it's pretty much killed off all my desire to roll my own. I'm generally a huge fan of lambdas and have gotten used thinking in expressions. Although even with that, I wasn't able to get comfortable with the latest Rhino.Mocks. Probably just me. But from the very first attempt, Moq worked like i think and I was up and running.
var mock = new Mock();
mock.Setup(x=> x.Bar).Returns("bar").AtMostOnce();
var foo = mock.Object;
Assert.AreEqual("bar",foo.Bar);
I'm a convert!
Labels: dream, mock, moq, tdd
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.
Labels: autofac, moq, tdd
A case for TDD
I know, it's been rather quiet here lately. I've just been slammed with coding, so writing things up is falling behind. In addition, my blogging time's going to be split between
techblog.notify.me and
www.mindtouch.com/blog. And I'm behind on both of those as well. I should have some fun
Dream and
DekiScript stuff for the mindtouch blog and some asynchronous programming for the
notify.me blog soon. As soon as i can get myself to stop coding again.
So what makes me stop coding for a minute to babble on? It's just a quick case studio of why TDD is important.
I've been an Inversion of Control/Dependency Injection for about a year and a half, and while I've eased my way into it, I'm pretty much at the "an interface for every class" stage of having everything abstracted so i can easily mock things. But here and there, I take in third party assemblies for my projects. And most of the time, they are not well interfaced. And generally I try to create a facade that is interfaced, so i can test my interaction in isolation. But depending on how many secondary classes their code uses, sometimes my facade gets lazy leaving places i can't mock.
Now, i'm pretty religious about test coverage, but i do have holes where my facade leaves untestable bits. And this is where TDD shows it's worth. Because when a feature is added or a refactor happens, almost with 100% certainty, the bugs that manage to get into production are in the code that doesn't have test coverage.
The lesson here is that the time saved in not building a properly mockable facade, thereby torpedoing my testability, is repaid manyfold in debugging later as bugs make it into production. meh.
Labels: c#, mindtouch, notify.me, resharper, tdd
TDD & you can't test what you can't measure
Recently I've been dealing with a lot of bug fixing that I can't find a good way to wrap tests around. Which is really annoying, because it means that as things get refactored these bugs can come back. These scenarios are almost always UI related, whether it's making sure that widgets behave as expected, or monitoring the visual state of an external application I'm controlling (Live For Speed, in this case). What all these problems have in common is that the recognition of a bug existing can only be divined by an operator, because somewhere there is lack of instrumentation that could programatically tell the state I'm looking for. And to paraphrase the old management saying, "You can't test what you can't measure".
My best solution is the usual decoupling of business logic from UI. Make everything a user can do an explicit function of your model and now you can test the functions with unit tests. At least you business logic is solid, even if your presentation gets left in the cold. And depending on your UI layer, a lot of instrumentation can still be strapped on. WinForms controls are generally so rich that nearly everything you would want to test for you can probably query from the controls. But things that you can test and see within a second may be a lot of lines of code to test programatically and of course go right out the window when you refactor your UI. And if your trying to test the proper visual states of a DataGridView and its associated bindings, then you're in for some serious automation pains.
I know that business logic is the heart of the application, but presentation is what people interact with and if it's poor, then it doesn't matter how kick ass your back end is. So for the time being that means that UI takes a disproportionate amount of time to run through its possible states and it's something I would like to handle more efficiently.
Labels: .net, c#, LFS, tdd