chevron-thin-right chevron-thin-left brand cancel-circle search youtube-icon google-plus-icon linkedin-icon facebook-icon twitter-icon toolbox download check linkedin phone twitter-old google-plus facebook profile-male chat calendar profile-male
0 votes
I'm trying to mock an Autofac resolve, such as

    using System;
    using Autofac;
    using TypeMock.ArrangeActAssert;

    class Program
    {
        static void Main(string[] args)
        {
            var inst = Isolate.Fake.Instance<IContainer>();
            Isolate.Fake.StaticMethods(typeof(ResolutionExtensions), Members.ReturnNulls);
            Isolate.WhenCalled(() => inst.Resolve<IRubber>()).WillReturn(new BubbleGum());
            Console.Out.WriteLine(inst.Resolve<IRubber>());
        }
    }

    public interface IRubber
    {}

    public class BubbleGum : IRubber
    {}


Coming from Moq, the syntax and exceptions from TypeMock still confuse me a bit...:oops: Having initially run this in a TestMethod, I kept getting an exception resembling "WhenCalled cannot be run without a complementing behavior". I tried defining behaviors for everyone and their mothers, but to no avail.

Then I debug stepped through the test run, and saw that an actual exception was fired from Autofac: IRubber has not been registered.

So it's obvious that the static Resolve<T> function isn't being faked, and I can't get it to be faked, no matter how I go about hooking it up.

Isolate.WhenCalled(() => ResolutionExtensions.Resolve<IRubber>(null)).WillReturn(new BubbleGum());


... throws an exception from Autofac complaining that the IComponentContext cannot be null. Feeding it the presumably faked IContainer (or faking an IComponentContext instead) gets me back to the "IRubber not registered" error.

Any pro tips? :)
asked by lockshopr (640 points)

2 Answers

0 votes
While you should be able to do this with the code you provided, it seems like a bug in resolving the extension method chain, which we are currently investigating. I opened a support ticket, and I will update you on the progress.

In the mean time, might I suggest a different approach? Being an IoC container, Autofac can be injected into your class under test using a test container. You might want to consider testing something that uses the resolve from Autofac, rather than the resolve itself.

[Test]
public void Test1()
{
    var builder = new ContainerBuilder();
    builder.RegisterType<BubbleGum>().As<IRubber>();
    var testContainer = builder.Build();
    var underTest = new UnderTest(testContainer);

    var result = underTest.GetRubber();

    Assert.AreEqual(typeof(BubbleGum), result.GetType());
}

public class UnderTest
{
    public IContainer Container { get; private set; }

    public UnderTest(IContainer container)
    {
        Container = container;
    }

    public IRubber GetRubber()
   {
        // your logic here
       return Container.Resolve<IRubber>();
    }
}


Another approach is bypass the container altogether using Isolator:

[Test]
public void Test2()
{
    var underTest = new UnderTest(null);
    Isolate.WhenCalled(() => underTest.GetRubber()).WillReturn(new BubbleGum());

    var result = underTest.GetRubber();

    Assert.AreEqual(typeof(BubbleGum), result.GetType());
}


Hope that helps.
answered by igal (5.7k points)
0 votes
Thanks, igal.

The main issue I'm facing is that Autofac's Resolve methods, which are used by the class I'm testing, are extension methods. The class I'm testing is actually a Autofac based implementation of a generic factory interface in my project, so the test is assuming that the Resolve function is being called. If I swap Autofac with another interface, I'll just keep pushing my actual problem further away :-)
answered by lockshopr (640 points)
...