当前位置:  开发笔记 > 编程语言 > 正文

Rhino Mocks - Stub .Expect vs .AssertWasCalled

如何解决《RhinoMocks-Stub.Expectvs.AssertWasCalled》经验,为你挑选了1个好方法。

好吧,我知道在Rhino Mocks中对新的AAA语法有很多困惑,但我必须说实话,从我到目前为止看到的,我喜欢.它读得更好,并节省了一些按键.

基本上,我正在测试一个ListController基本上将负责一些事情列表:)我已经创建了一个最终将成为DAL的接口,这当然是存在的.

我有以下代码:

(manager是被测系统,data是存根数据接口)

    [Fact]
    public void list_count_queries_data()
    {
        data.Expect(x => x.ListCount(1));
        manager.ListCount();
        data.VerifyAllExpectations();
    }

此测试的主要目的是确保经理实际查询DAL.请注意,DAL实际上并不存在,因此没有"实际"值返回..

但是,这是失败的,因为我需要将期望值更改为具有返回值,例如:

        data.Expect(x => x.ListCount(1)).Return(1);

然后这将运行正常,测试将通过,令我困惑的是,此时,返回值没有任何意义.我可以将它改为100,50,42,无论如何,测试总会通过?

这让我感到紧张,因为测试应该是明确的,如果不能满足预期的条件,应该完全失败吗?

如果我将测试更改为("1"是计数链接到的预期ID):

    [Fact]
    public void list_count_queries_data()
    {
        manager.ListCount();
        data.AssertWasCalled(x => x.ListCount(1));
    }

这一切都很顺利,如果我将测试切换到它的头部AssertWasNotCalled,它会按预期失败.我也认为它看起来好多了,更清楚正在测试什么,最重要的是PASSES和FAILS如预期的那样!

那么,我在第一个代码示例中遗漏了什么?你对存根断言有什么看法?(有一些有趣的讨论在这里,我个人也很喜欢这种反应.



1> Mark Simpson..:

你的测试试图达到什么目的?

您正在验证哪种行为或状态?具体来说,您是在验证协作者(数据)是否正在ListCount调用其方法(基于交互的测试),或者您是否只想ListCount返回一个预设值来驱动被测试的类,同时在其他位置验证结果(传统的基于状态的测试) ?

如果你想设置一个期望,使用模拟和期望:使用MockRepository.CreateMock()myMock.Expect(x => x.ListCount())

如果要存根方法,请使用MockRepository.CreateStub()myStub.Stub(x => x.ListCount()).

(除此之外:我知道你可以使用stub.AssertWasCalled()来实现与mock.Expect相同的东西,并且可以说是更好的阅读语法,但我只是钻进了模拟和存根之间的区别).

Roy Osherove对模拟和存根有一个非常好的解释.

请发布更多代码!

我们需要一个完整的图片,说明如何创建存根(或模拟)以及如何使用结果来测试被测试的类.是否ListCount有一个输入参数?如果是这样,它代表什么?你是否关心它是否具有一定的价值?如果ListCount 返回某个值,你关心吗?

正如Simon Laroche指出的那样,如果Manager实际上没有对ListCount的模拟/存根返回值做任何事情,那么测试将不会因为它而通过或失败.所有测试都会期望调用mocked/stubbed方法 - 仅此而已.

为了更好地理解这个问题,请考虑三条信息,您很快就会想到这一点:

    正在测试什么

    在什么情况下?

    预期结果是什么?

比较: 基于交互的测试与模拟.对模拟的调用测试.

[Test]
public void calling_ListCount_calls_ListCount_on_DAL()
{
   // Arrange
   var dalMock = MockRepository.Mock();
   var dalMock.Expect(x => x.ListCount()).Returns(1);
   var manager = new Manager(dalMock);

   // Act
   manager.ListCount();

   // Assert -- Test is 100% interaction based
   dalMock.VerifyAllExpectations();   
}

基于状态的测试与存根.存根驱动测试,但不是期望的一部分.

[Test]
public void calling_ListCount_returns_same_count_as_DAL()
{
   // Arrange
   var dalStub = MockRepository.Stub();
   var dalStub.Stub(x => x.ListCount()).Returns(1);
   var manager = new Manager(dalMock);

   // Act
   int listCount = manager.ListCount();

   // Assert -- Test is 100% state based
   Assert.That(listCount, Is.EqualTo(1),
       "count should've been identical to the one returned by the dal!");
}

我个人赞成尽可能基于状态的测试,尽管通常需要基于交互的测试来设计使用Tell,不要记住,因为您不会有任何暴露状态需要验证!

API混淆.模拟不是存根.或者是他们?

犀牛嘲笑中的模拟和存根之间的区别是混乱的.传统上,存根并不意味着期望 - 所以如果你的测试double没有调用它的方法,这不会直接导致测试失败.

...但是,Rhino Mocks API功能强大,但令人困惑,因为它可以让你设置对存根的期望,对我来说,这违背了公认的术语.我也不会考虑很多术语.在我看来,如果区分被消除并且在测试中调用的方法设置了角色会更好.

推荐阅读
jerry613
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有