使用Autofac和Moq模拟服务库中的代表工厂

时间:2018-08-07 20:07:29

标签: moq autofac factories

我有一个简单的控制台应用程序,它使用Autofac作为IoC容器。

class Program
{
    static IContainer container;

    static void Main(string[] args)
    {
        container = Configure();
        Run();
    }

    private static void Run()
    {
        using (var scope = container.BeginLifetimeScope())
        {
            var t = scope.Resolve<ITest1>();
            var s = t.TestMethod1("");
            Console.WriteLine(s);
        }
    }

    private static IContainer Configure()
    {
        var builder = new ContainerBuilder();

        builder.RegisterType<TestClass1>()
                .As<ITest1>();

        builder.RegisterType<TestClass2>()
                .As<ITest2>();

        return builder.Build();
    }
}

应用程序在“ TestClass1”中调用方法“ TestMethod1”。

public interface ITest1
{
    string TestMethod1(string s);
}

public class TestClass1 : ITest1
{
    ITest2 f;

    public TestClass1(Func<ITest2> test2Factory)
    {
        f = test2Factory();
    }

    public string TestMethod1(string s)
    {
        var r = string.Empty;

        r = f.TestMethod2(s);
        r += ":TestMethod1";

        return r;
    }
}

TestClass1依赖于TestClass2,后者为Autofac声明了与TestClass1构造函数一起使用的委托工厂。

public interface ITest2
{
    string TestMethod2(string s);
}

public class TestClass2 : ITest2
{
    public delegate TestClass2 Factory();

    public virtual string TestMethod2(string s)
    {
        return ":TestMethod2";
    }
}

这一切都按预期工作-Autofac解析了TestClass2依赖项,我得到了输出“:TestMethod2:TestMethod1”。

现在,我想使用Moq和Autofac.Extras.Moq扩展名模拟TestClass2。我将以下方法添加到控制台应用程序,然后从Program Main方法调用它。

private static void Test()
{
    using (var mock = AutoMock.GetLoose())
    {
        mock.Mock<TestClass2>()
        .Setup(t => t.TestMethod2(""))
        .Returns(":NOT_TEST_METHOD2");

        var s = mock.Create<TestClass1>();
        var r = s.TestMethod1("cheese");
        Console.WriteLine(r);
    }
}

现在,当我期望“:NOT_TEST_METHOD2:TestMethod1”时,我得到输出“:TestMethod1”。似乎尚未调用该模拟程序。当我单步执行代码时就可以确认这一点。

我也曾尝试过使用嘲讽(mock.Provide())来解决模拟问题,正如其他地方所建议的(见下文)。还是没有运气。

var wc = Moq.Mock.Of<TestClass2>(f => f.TestMethod2("") == ":NOT_TEST_METHOD2");
Func<string, ITest2> factory = x => wc;
mock.Provide(factory);

这似乎是一个非常简单的场景,但是我在任何地方都找不到有效的答案。谁能看到我在做什么错? 感谢您的帮助!

2 个答案:

答案 0 :(得分:0)

我不使用AutoMock支持,但是我知道我的Autofac,因此可以尝试一下。

看起来TestClass1在其构造函数中使用的是ITest2而不是TestClass2,我猜是否您已切换到此:

mock.Mock<ITest2>()
    .Setup(t => t.TestMethod2(""))
    .Returns(":NOT_TEST_METHOD2");

...那么它可能会起作用。

答案 1 :(得分:0)

谢谢特拉维斯。您的建议对我没有用,但使我对问题有所不同,退后一步使我意识到我正在寻找不需要一个复杂解决方案的解决方案。也就是说,只需要Moq,而不需要Autofac AutoMock扩展。以下代码有效:

private static void Test()
{
    Func<ITest2> func = () =>
    {
        var x = new Mock<ITest2>();
        x.Setup(t => t.TestMethod2("")).Returns(":NOT_TEST_METHOD2");
        return x.Object;
    };

    var s = new TestClass1(func);
    var r = s.TestMethod1("");
}

帖子Using Moq to Mock a Func<> constructor parameter and Verify it was called twice回答了这个问题。