Rhino Mocks:AAA Synax:断言属性已设置为给定类型

发布于 2024-10-23 20:14:41 字数 1690 浏览 1 评论 0原文

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

这就是我想要做的,并且无论 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);
    }

I am trying to assert that a property in a mock object was set with a given type. The property has an abstract type and is set with one of a number of concrete types.

This is what I'm trying to do, and it's always passing the test regardless of the value that Foo.DoSomething() sets Foo.Bar with:

    [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)));
    }

The Rhino 3.5 / AAA Documentation describes how to set expectations on property sets having a given value, but I just want to check the type of the value.

How does one assert on a property set, specifically on a property set having a given parameter type?


Update:
The example above is oversimplified. What I'm actually testing is an individual state class. It's one of several states that a "parent object" (the object having the state, Foo in this case) can be in. I was verifying that the state under test (call it BarOne) correctly set Foo.State to an instance of BarTwo when it was time to transition states.

A clearer example (with the accepted solution implemented) would be:

    [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);
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

难忘№最初的完美 2024-10-30 20:14:41

也许是这样的:

[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 必须是虚拟的。模拟接口并测试类如何使用依赖项通常总是更好,而不是测试类如何使用自身(这通常表明过度测试,或者

在您的情况下,是一个模拟 )。甚至需要?您只是使用有点复杂的语法来断言真实行为的结果,除了属性的设置者之外,没有什么真正被模拟的。有时,为什么不做一些事情呢?像这样:

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

Perhaps something like this:

[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();
}

So what's going on..

We changed the assertion to be an Expect. I find this a little bit cleaner, also the expectation allows us a cleaner verification of what the type is. We are Saying "Expect that Bar will be set to an instance of CorrectBarSubclass. Then we Act, and we assert that our expectation was met.

Couple of things: Any time you Mock a class, anything you have an Expect or Stub call on must be virtual or abstract, so in this case, Bar must be virtual. It's usually always better to mock an interface and test how a class uses a dependency, rather than testing how a class uses itself (that usually is an indication of over-testing, or incorrect separation of concerns).

In your case, is a mock even required? You are just using a somewhat complicated syntax to assert the result of a real behavior, nothing is really mocked other than the setter of a property. Sometimes it's just easier, and more appropriate, to test real behaviors. Why not do something like this:

var foo = new Foo();
foo.DoSomething();
Assert.That(foo.Bar is CorrectBarSubclass);
尛丟丟 2024-10-30 20:14:41

我遇到了类似的问题,我尝试将谓词表达式存根到包含字符串(当然是不可变的)的 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 存根问题。

I've had similar problem where I tried to stub predicate expression to Find-method which contains string (which is immutable of course). No success until I've create testPredicate which I pass to stub, actual SUT and finally to assert. Below code works.

    [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));
    }

EDIT: this answer was mended and sended to correct IQueryable Stub-question.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文