我可以复制Moq Mock实现吗?

时间:2014-09-18 15:20:50

标签: c# .net unit-testing mocking moq

我一直在使用Moq并喜欢它,但我遇到了一个模拟一些遗留代码的问题(在我尝试重构之前)

我真正想做的是有两个独立的模拟,只有略微不同的实现,例如下面的示例。

        Mock<IFoo> fooMock = new Mock<IFoo>();
        fooMock.SetupGet(f => f.bar).Returns(7);
        fooMock.SetupGet(f => f.bar2).Returns(3);
        Mock<IFoo> fooMockClone = new Mock<IFoo>(fooMock.Behavior);
        fooMockClone.SetupGet(f => f.bar).Returns(9);

        Debug.Assert(7 == fooMock.Object.bar);
        Debug.Assert(9 == fooMockClone.Object.bar);
        Debug.Assert(3 == fooMockClone.Object.bar2);
        Debug.Assert(3 == fooMock.Object.bar2);

这是一个简单的例子,但真正的代码是一个有很多方法的对象,我希望两个版本的实现略有不同。

由于

2 个答案:

答案 0 :(得分:1)

我想知道在这种情况下你是否正在寻找行为测试。这里是Machine.Fakes中Moq子层的一个示例......它允许您似乎想要的嵌套,同时仍然保持测试的逻辑分离。需要NuGet包:Machine.Fakes.Moq,Machine.Specifications.Should

class IFoo_test_context : WithSubject<IFoo>
{
    Establish context = () => Subject.bar2 = 3;
}

class When_fooing_with_seven : IFoo_test_context
{
    Establish context = () => Subject.bar = 7;

    It bar_should_be_seven =()=> Subject.bar.ShouldEqual(7);
    It bar2_should_be_three =()=> Subject.bar.ShouldEqual(3);
}

class When_fooing_with_nine : IFoo_test_context
{
    Establish context = () => Subject.bar = 9;

    It bar_should_be_nine = () => Subject.bar.ShouldEqual(9);
    It bar2_should_be_three = () => Subject.bar.ShouldEqual(3);
}

这个例子有点愚蠢,因为它测试了嘲弄行为,但很难看出你最终想要完成什么。据我所知,没有复制构造函数以你想要的方式使用Mock。

答案 1 :(得分:0)

您不会模拟实现细节,您可以模拟值,以便您可以在代码中找到需要测试的点。编写一个测试模拟依赖项输出值的测试没有意义,那么你只是测试moq。

例如:

public class Stuff {
    IFoo _foo;
    IBar _bar;
    public Stuff(IFoo foo, IBar bar){
        _foo = foo;
        _bar = bar;
    }
    public void DoStuff() {
        if(_foo.HasFooage) {
            _bar.Bar = 4;
        }
    }
}

然后你的测试会:

...
public void test_bar_does_bar() {
    var foo = new Mock<IFoo>();
    foo.Setup(f => f.HasFooage).Returns(true);
    var bar = new Mock<IBar>();
    var stuff = new Stuff(foo.Object, bar.Object);

    stuff.DoStuff();

    Assert.That(bar.Bar, Is.EqualTo(4));
}