4

我一直在嘲笑使用 m​​oq 并且总是发现自己在做这样的事情:

假设我要测试的行为是 classUnderTest.DoSomething() 调用 l.Fatal("My test message") 一次。

//arrange
mockLogger.Setup(l => l.Fatal("My test message"));

//act
classUnderTest.DoSomething()

//assert
mockLogger.Verify(l => l.Fatal("My test message"), Times.Once());

我觉得验证调用总是重复设置,除了 Times 参数。即使使用不同的模拟框架,我也很想知道其他人在做什么。有一个更好的方法吗?

4

4 回答 4

4

如果您确实需要控制 Mock 对象的行为,例如返回内容,则只需对 Mock 对象进行设置:

_mockRepo.SetUp(m => m.DoStuff()).Returns(someObject);

或抛出异常:

_mockRepo.SetUp(m => m.DoStuff()).Throws(new SomeExceptionType());

我假设,在您的示例中,您将 logger 模拟对象传递给其他正在测试的对象,在这种情况下,删除 setup 调用将不起作用,因为只需创建 Mock 对象即可完成等效设置。

编辑

public class Dude : IDude
{
    private IAirSupport _support;

    public Dude(IAirSupport support)
    {
        _support = support;
    }

    public void Advance(Place place)
    {
        if(place.IsUnderAttack)
        {
            _support.CoveringFire(place);
            MoveAndFire(place);
        }

    }
}

模拟这个:

var support = new Mock<IAirSupport>();

var dude = new Dude(support.Object);

var place = new HotSpot { IsUnderFire = true };


dude.Advance(place);

support.Verify(m => m.CoveringFire(place), Times.Once());

这就是您所需要的 - 验证完成所有繁重的工作,无需调用设置。

于 2012-11-23T12:47:53.473 回答
2

我同意你的观点,即感觉重复。但是,在这种特殊情况下,我认为您不需要打电话Setup(),因为您没有返回任何东西。我通常只Setup()在需要根据返回的对象断言某些内容时才调用。

最近我开始通过结构映射使用 AutoMocking,这促使我在基类上编写了一些快捷方式/实用方法来访问自动生成的模拟。然后我也可以编写一个快捷方式来调用Verify()。它可能会为您节省一两次击键... http://evolutionarydeveloper.blogspot.co.uk/2012/10/automock-with-structuremap-and-moq.html

于 2012-11-23T12:18:26.023 回答
1

尝试像这样重新安排您的测试

   //arrange
   var mockLogger = new Mock<ILogger>();
   var classUnderTest = new Foo(mockLogger.Object);

   //act
   classUnderTest.DoSomething();

   //assert
   mockLogger.Verify(l => l.Fatal("My test message"), Times.Once());

这样您就不需要双重断言,也不需要重复的测试数据。基本上,我建议要么通过使用Setup 使用Verify语法预先设置预期的调用来进行严格的模拟。我个人更喜欢验证语法,因为断言的内容非常清楚。

于 2012-11-23T15:30:28.040 回答
0

我同意很多测试感觉重复,但我不认为事情可以比你描述的更容易。

所有单元测试都遵循以下模式:setup-execute-assert(至少是好的)。这正是您的示例优雅地所做的。你可以争论你是如何设置的,你是如何断言的,但是你已经在一行代码中完成了每一个,并且很难找到一种方法来达到顶峰。

于 2012-11-23T13:34:05.397 回答