如何使用Moq测试方法调用顺序

Fin*_*las 28 c# unit-testing moq

目前我有:

    [Test]
    public void DrawDrawsAllScreensInTheReverseOrderOfTheStack() {
        // Arrange.
        var screenMockOne = new Mock<IScreen>();
        var screenMockTwo = new Mock<IScreen>();
        var screens = new List<IScreen>();
        screens.Add(screenMockOne.Object);
        screens.Add(screenMockTwo.Object);
        var stackOfScreensMock = new Mock<IScreenStack>();
        stackOfScreensMock.Setup(s => s.ToArray()).Returns(screens.ToArray());
        var screenManager = new ScreenManager(stackOfScreensMock.Object);
        // Act.
        screenManager.Draw(new Mock<GameTime>().Object);
        // Assert.
        screenMockOne.Verify(smo => smo.Draw(It.IsAny<GameTime>()), Times.Once(),
            "Draw was not called on screen mock one");
        screenMockTwo.Verify(smo => smo.Draw(It.IsAny<GameTime>()), Times.Once(), 
            "Draw was not called on screen mock two");
    }
Run Code Online (Sandbox Code Playgroud)

但是我在生产代码中绘制对象的顺序并不重要.我可以先做一个,或者两个没关系.然而,它应该重要,因为绘制顺序很重要.

你如何(使用Moq)确保按特定顺序调用方法?

编辑

我摆脱了那个考验.draw方法已从我的单元测试中删除.我只需要手动测试它的工作原理.尽管顺序的逆转被带入了一个单独的测试类,在那里测试它并不是一件坏事.

感谢您关注的功能链接.我当然希望它能很快得到补充,非常方便.

Dec*_*lan 31

我最近创建了Moq.Sequences,它提供了检查Moq中的排序的能力.您可能想阅读描述以下内容的帖子:

  • 支持方法调用,属性设置器和getter.
  • 允许您指定应该预期特定呼叫的次数.
  • 提供循环,允许您将呼叫分组到定期组.
  • 允许您指定应该预期循环的次数.
  • 预期按顺序调用的调用可以与任何顺序中预期的调用混合.
  • 多线程支持.

典型用法如下:

[Test]
public void Should_show_each_post_with_most_recent_first_using_sequences()
{
    var olderPost = new Post { DateTime = new DateTime(2010, 1, 1) };
    var newerPost = new Post { DateTime = new DateTime(2010, 1, 2) };
    var posts = new List<Post> { newerPost, olderPost };

    var mockView = new Mock<BlogView>();

    using (Sequence.Create())
    {
        mockView.Setup(v => v.ShowPost(newerPost)).InSequence();
        mockView.Setup(v => v.ShowPost(olderPost)).InSequence();

        new BlogPresenter(mockView.Object).Show(posts);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这是Moq的一个很棒的扩展; 对我来说,缺乏序列支持是项目中的主要遗漏.IMO应将其拉入主干(https://github.com/dwhelan/Moq-Sequences). (2认同)

Kaj*_*ils 14

使用Moq CallBacks的简单解决方案:

    [TestMethod]
    public void CallInOrder()
    {
        // Arrange
        string callOrder = "";

        var service = new Mock<MyService>();
        service.Setup(p=>p.FirstCall()).Returns(0).CallBack(()=>callOrder += "1");
        service.Setup(p=>p.SecondCall()).Returns(0).CallBack(()=>callOrder += "2");

        var sut = new Client(service);

        // Act
        sut.DoStuff();

        // Assert
        Assert.AreEqual("12", callOrder);
    }
Run Code Online (Sandbox Code Playgroud)


Tru*_*ill 5

目前似乎还没有实施。见第 24 期: MockSequence这个线程讨论了这个问题。

不过,您可能会考虑修改您的测试。我通常觉得测试顺序会导致测试脆弱,因为它经常测试实现细节。

编辑:我不确定这是否解决了 OP 的问题。卢塞罗的回答可能更有帮助。