Rhino Mocks:AAA Synax:使用给定类型设置Assert属性

时间:2011-03-18 01:45:30

标签: c# unit-testing nunit rhino-mocks

我试图断言模拟对象中的属性是使用给定类型设置的。该属性具有抽象类型,并使用多种具体类型之一进行设置。

这就是我正在尝试做的事情,无论Foo.DoSomething()设置Foo.Bar的值如何,它总是通过测试:

    [Test]
    public void DoSomething_SetsCorrectBar()
    {
        // Arrange
        Foo foo = MockRepository.GenerateMock<Foo>(); // Creates mock in Replay mode (what I want for AAA syntax).

        // Act
        foo.DoSomething();

        // Assert that DoSomething set Foo.Bar to an instance of CorrectBarSubclass
        foo.AssertWasCalled(foo => foo.Bar = null, options => options.WhenCalled(invocation => Assert.That(invocation.Arguments[0] is CorrectBarSubclass)));
    }

Rhino 3.5 / AAA Documentation描述了如何设置具有给定值的属性集的期望,但我只想检查值的类型。

如何在属性集上断言,特别是在具有给定参数类型的属性集上?


更新 上面的例子过于简单了。我实际测试的是一个单独的州级课程。这是“父对象”(具有状态的对象,在这种情况下为Foo)可以进入的几个状态之一。我正在验证被测试状态(称为BarOne)正确地将Foo.State设置为BarTwo的实例何时是过渡国家的时候。

一个更清晰的例子(实施已接受的解决方案)将是:

    [Test]
    public void BarOne_DoSomething_SetsNextState()
    {
        // Arrange
        Foo foo = MockRepository.GenerateMock<Foo>(); // Creates mock in Replay mode (what I want for AAA syntax).
        foo.Stub(x => x.CreateBarTwoState()).Return(new BarTwo(foo));
        BarOne bar = new BarOne(foo); // We are testing the BarOne state independently of Foo, that's why we mock Foo but instantiate BarOne.

        // Act
        bar.DoSomething();

        // Assert that DoSomething set Foo.Bar to an instance of BarTwo
        foo.AssertWasCalled(foo => foo.Bar = Arg<BarTwo>.Is.TypeOf);
    }

2 个答案:

答案 0 :(得分:4)

也许是这样的:

[Test]
public void AddPlayer_GivesGameEnoughPlayersToStart_SetsNextState()
{
    // Arrange
    Foo foo = MockRepository.GenerateMock<Foo>(); // Creates mock in Replay mode (what I want for AAA syntax).
    foo.Expect(m => m.Bar = Arg<CorrectBarSubclass>.Is.TypeOf);
    // Act
    foo.DoSomething();
    //Assert
    foo.VerifyAllExpectations();
}

那是怎么回事......

我们将断言改为Expect。我觉得这有点清洁,期望也可以让我们更清楚地确认类型是什么。我们正在说“期望Bar将被设置为CorrectBarSubclass的实例。然后我们采取行动,我们断言我们的期望得到满足。

一些事情:每当你模拟一个课时,你有ExpectStub调用的任何东西都必须是虚拟的或抽象的,所以在这种情况下,Bar必须是虚拟的。通常总是更好的模拟接口并测试类如何使用依赖项,而不是测试类如何使用自身(通常表示过度测试或不正确的关注点分离)。

在你的情况下,是否需要模拟?您只是使用一种有点复杂的语法来断言真实行为的结果,除了属性的setter之外,没有任何东西真的被嘲笑。有时,测试真实行为更容易,也更合适。为什么不这样做:

var foo = new Foo();
foo.DoSomething();
Assert.That(foo.Bar is CorrectBarSubclass);

答案 1 :(得分:3)

我遇到了类似的问题,我试图将谓词表达式存根到包含字符串的Find-method(当然是不可变的)。没有成功,直到我创建testPredicate,我传递给存根,实际SUT,最后断言。下面的代码可以使用。

    [Test()]
    public void Search_Apartment_With_Spesific_Address()
    {
        //ARRANGE
        var repositoryMock = MockRepository.GenerateMock<IApartmentRepository>();
        var notificationMock = MockRepository.GenerateMock<INotificationService>();
        var service = new ApartmentService(repositoryMock, notificationMock);
        var apartment = new List<Apartment> {new Apartment {Address = "Elm Street 2"}}.AsQueryable();

        Expression<Func<Apartment, bool>> testPredicate = a => a.Address == "Elm Street 2";
        repositoryMock.Stub(x => x.Find(testPredicate)).Return(apartment);

        //ACT
        service.Find(testPredicate);

        //ASSERT
        repositoryMock.AssertWasCalled(x => x.Find(testPredicate));
    }

编辑:这个答案被修补并发送以纠正IQueryable Stub-question。