3

使用新的 Rhino Mocks 3.5 Arrange/Act/Assert (AAA) 测试风格,我在编写测试时遇到问题。

我有一个调用存储库类上的方法的方法。ActivateFoo,我的 Foo 对象有一个 IsActive 属性。ActivateFoo 对象的结果应该改变属性。

这是示例代码:

[TestMethod]
public void Should_update_foo_to_active_inside_of_repository()
{
  // arrange
  var repo = MockRepository.GenerateMock<IRepository>();
  var foo = new Foo() { ID = 1, IsActive = false };
  var target = new Presenter(repo);
  repo.Expect(x => x.ActivateFoo(foo)).Return(true);

  // act
  target.Activate(foo);

  // assert
  Assert.IsTrue(foo.IsActive);
  repo.VerifyAllExpectations();  
}

我猜关键代码段将在“ActivateFoo(foo))”之间。和“返回(真);”。

有一点要澄清方法链接的东西在幕后是如何工作的,如果在我期望的行上写了代码,它是在 Return() 之后还是之前有关系吗?(当然,除非解决方案是使用 Expect 的 MethodOptions 重载,或者其他)。

提前感谢您的帮助。

4

4 回答 4

1

感谢 AB Kolan,这是我使用和工作的结果代码。

[TestMethod]
public void Should_update_foo_to_active_inside_of_repository()
{
    // arrange
    var repo = MockRepository.GenerateMock<IRepository>();
    var foo = new Foo() { ID = 1, IsActive = false };
    var target = new Presenter(repo);
    repo.Expect(x => x.ActivateFoo(foo)).
        Do(new Func<Foo, bool>(
            delegate(Foo f) { f.IsActive = true; return true; }
        ));

    // act
    target.Activate(foo);

    // assert
    Assert.IsTrue(foo.IsActive);
    repo.VerifyAllExpectations();
}

我倾向于不喜欢有额外的函数方法来单独使用测试,如果可能的话,更喜欢内联委托。

为了解决这个问题,我应该做或不做设计。由于名称在那里,这不是 target.Activate() 方法的确切代码和内部。Activate() 中的代码进行一些检查,如果需要,将执行存储库 ActivateFoo(),然后检查该操作的结果并执行其他操作。

因此,可能稍后我将不得不重构它并分离步骤,但现在,我已经让它工作了。

谢谢

于 2009-03-11T18:52:49.987 回答
0

我还没有真正使用这个版本的 RhinoMocks,但在旧版本中,您必须使用 .Do(适当的委托) 来设置标志并返回值 (而不是 .Return)。

请让我知道它是否有效,否则我可以玩它。

于 2009-03-11T17:40:11.673 回答
0

从外观上看,ActivateFoo 应该是一个 void 方法。而且由于您正在模拟它,因此您不应该验证它是否会更改对象上的任何内容。

您将在测试存储库方法 ActivateFoo 时验证 IsActive 属性是否已更改,而不是在测试演示者上的 Activate 方法时更改。

于 2009-03-11T17:56:46.783 回答
0

您可能想使用 Do 处理程序尝试这样的事情。老实说,我觉得 ActivateFoo 应该是 void 返回类型。但这里是具有 bool 返回类型的 ActivateFoo 的代码。

    [TestMethod]
    public void Should_update_foo_to_active_inside_of_repository()
    {
        // arrange
        var repo = MockRepository.GenerateMock<IRepository>();
        var foo = new Foo() { ID = 1, IsActive = false };
        var target = new Presenter(repo);
        repo.Expect(x => x.ActivateFoo(foo)).
            Do(new ActivateFooDelegate(ActivateFooDelegateInstance));
        // act
        target.Activate(foo);

        // assert
        Assert.IsTrue(foo.IsActive);
        repo.VerifyAllExpectations();
    }

    private delegate bool ActivateFooDelegate(Foo f);

    public bool ActivateFooDelegateInstance(Foo f)
    {
        f.IsActive = true;
        return f.IsActive;
    }
于 2009-03-11T18:01:12.687 回答