【问题标题】:mixing stubs and mocks in rhino在犀牛中混合存根和模拟
【发布时间】:2010-11-10 14:52:30
【问题描述】:

我的测试试图断言调用了某个 dal 方法,并带有一些参数。 该方法返回一个DataSet 对象,所以我的模拟在调用时只返回一个空的DataSet

我遇到的问题是,当 SUT 没有使用正确的参数调用 dal 时,mock 不会返回空的DataSet,因此我的类在尝试访问空引用时会抛出异常。这只会导致测试失败,并在我的测试运行器中显示不相关的消息。

我想在所有情况下对方法进行存根以返回空的Dataset,以便该方法可以正常运行,并在测试结束时验证它是否使用预期的参数调用。我要求太多了吗?

【问题讨论】:

    标签: c# mocking rhino-mocks


    【解决方案1】:

    假设你的方法有一个 int 参数,这应该可以做到。

    IDal dalMock = MockRepository.GenerateMock<IDal>();
    
    // setup mock to return the emptyDataSet for any argument    
    dalMock
      .Stub(x => x.GetDataSet(Arg<int>.Is.Anything))
      .Return(emptyDataSet)
      .Repeat.Any();
    
    sut.Execute()
    
    // assert that the argument had been 7
    dalMock.AssertWasCalled(x => x.GetDataSet(Arg<int>.Is.Equal(7))
    

    Documentation of argument constraints.(这一章是我写的,不懂的可以问我;-)


    使用 .NET 2.0 看起来像这样:

    MockRepository mocks = new MockRepository();
    IDal dalMock = mocks.CreateDynamicMock<IDal>();
    
    // expect the correct argument
    Expect.Call(dalMock.GetDataSet(Arg<int>.Is.Equal(7)))
      .Return(emptyDataSet)
      .Repeat.Once();
    
    // setup mock to return the emptyDataSet for any argument    
    SetupResult.For(dalMock.GetDataSet(Arg<int>.Is.Anything))
      .Return(emptyDataSet)
      .Repeat.Any();
    
    sut.Execute()
    
    // assert that the argument had been 7
    mocks.VerifyAll();
    

    不能 100% 确定它是否有效,但应该。

    你也可以试试这个:

    // setup mock to return the emptyDataSet for any argument    
    SetupResult.For(dalMock.GetDataSet(Arg<int>.Is.Anything))
      .Do((GetDataSetDelegate)delegate(int i)
        {
          Assert.AreEqual(7, i);
        }
      .Return(emptyDataSet)
      .Repeat.Any();
    
    sut.Execute()
    

    Do 在调用 mock 时执行。它需要一个与模拟方法具有完全相同接口的委托。由于 .NET 2.0 的语法原因,您需要将其强制转换为正确的委托类型,因此您需要先声明它(在这种情况下为GetDataSetDelegate)。

    Rhino 3.5 用户注意事项:有一种更方便的调用方式:WhenCalled 只接受一个 lambda 作为参数,但必须以不同的方式实现。

    分别使用DoWhenCalled,您可以在调用模拟时实现参数断言。

    【讨论】:

    • 感谢您的提示和链接。所以我没有办法用参数设定期望,用“其他一切”设定存根?由于我在 VS2005 上使用 .NET 2.0,我不能使用 lambda 和扩展方法,这使得它变得更加丑陋,我想尽量减少使用。
    • 您可以使用旧语法。我尝试将其添加到答案中。
    • 目前我确实使用 AAA 语法。我只是使用 RhinoMocksExtensions.Stub(dal, delegate.Is.Anything); }).Return(新数据集());但我想我会让 dal 总是存根方法,然后像你建议的那样将期望添加为“AssertWasCalled”。再次感谢。
    【解决方案2】:

    您是否尝试过如here 所述将部分模拟与 Rhino Mocks 一起使用。我想如果你这样做,你就会得到你想要的。

    【讨论】:

    • 使用部分模拟是一个非常糟糕的主意:只有当您需要模拟没有接口且不受您控制的东西时才应该使用它们 - 换句话说,如果您非常绝望。
    • 我从来没有说过这是个好主意。这是他遇到的问题的一个想法。那么你有什么更好的主意?
    猜你喜欢
    • 2011-11-08
    • 2011-09-22
    • 1970-01-01
    • 2011-02-15
    • 2010-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-29
    相关资源
    最近更新 更多