1

我有一个简单的控制台应用程序,它使用 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);

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

4

2 回答 2

0

谢谢特拉维斯。你的建议对我没有用,但它让我以不同的方式思考这个问题,退后一步让我意识到我正在寻找一个不需要的复杂解决方案。也就是说,只需要起订量,不需要 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("");
}

这篇文章使用 Moq 模拟 Func<> 构造函数参数并验证它被调用了两次,从而回答了这个问题。

于 2018-08-10T08:42:45.003 回答
0

我不使用AutoMock支持,但我知道我的 Autofac,所以我可以试一试。

看起来它的构造函数中TestClass1需要一个ITest2而不是一个TestClass2,我猜你是否切换到这个:

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

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

于 2018-08-08T20:22:37.317 回答