Rhino Mocks:修复AssertWasCalled用于处置对象

时间:2010-02-25 18:27:39

标签: unit-testing rhino-mocks

我有一个看起来有点像这样的测试(我正在简化我的实际问题):

[Test]
public void Eat_calls_consumption_tracker_OnConsume()
{
   var consumptionTrackerStub = 
      MockRepository.GenerateStub<IConsumptionTracker>();
   var monkey = new Monkey(consumptionTrackerStub);
   var banana = new Banana();

   monkey.Eat(banana);

   consumptionTrackerStub.AssertWasCalled(x => x.OnConsume(banana));
}

除了Monkey在吃完Banana之后处理Banana.Equals之外,这样做会很好。因此,香蕉对象不再处于可用状态。特别是,Dispose实现在调用AssertWasCalled后无法工作,因为它使用已释放的非托管资源。

不幸的是Banana.Equals会导致{{1}}被调用,这会导致测试失败。解决这个问题的最佳方法是什么?

4 个答案:

答案 0 :(得分:2)

我倾向于建议实例化对象的类应该处理它。将香蕉传递给猴子,然后在消费后将其信任为Dispose,这绝不是一个好主意。

你能否将实例化Banana所需的数据传递给Monkey,而不是Banana本身?或者,你可以不在你的通话类中处理它吗?

答案 1 :(得分:1)

如果Monkey.Eat有参数IBanana(或IFood),IBanana来自IDisposable怎么办?然后你可以模拟IBanana,甚至验证是否已经调用了Dispose。

编辑:您可以使用Moq

执行此操作
[Test]
public void Eat_calls_consumption_tracker_OnConsume()
{
    var consumptionTrackerStub = new Mock<IConsumptionTracker>();
    var monkey = new Monkey(consumptionTrackerStub.Object);
    var banana = new Banana();
    monkey.Eat(banana);

    consumptionTrackerStub.Verify(x => x.OnConsume(It.IsAny<Banana>()));
}

public class Banana
{
    public override bool Equals(object obj)
    {
        throw new ObjectDisposedException("Banana");
    }
}

public class Monkey
{
    public Monkey(IConsumptionTracker tracker)
    {
        _tracker = tracker;
    }

    public void Eat(object obj)
    {
        _tracker.OnConsume(obj);
    }

    private readonly IConsumptionTracker _tracker;
}

public interface IConsumptionTracker
{
    void OnConsume(object obj);
}

答案 2 :(得分:0)

几种可能的解决方案:

  1. 也许你可以放松你的断言:你真的需要检查一下吃过的东西是香蕉吗?
  2. 在OnConsume上使用内联回调并断言它是香蕉而不是其他一些水果。这个回调将在处理香蕉之前执行。
  3. 顺便说一句:现在我想到了,我认为你的代码有一个概念性的问题:你怎么知道OnConsume的一些实现不想让香蕉去皮?

答案 3 :(得分:0)

原来你可以强迫Rhino Mocks用这样的object.ReferenceEquals检查参数:

[Test]
public void Eat_calls_consumption_tracker_OnConsume()
{
   var consumptionTrackerStub = 
      MockRepository.GenerateStub<IConsumptionTracker>();
   var monkey = new Monkey(consumptionTrackerStub);
   var banana = new Banana();

   monkey.Eat(banana);

   consumptionTrackerStub.AssertWasCalled(
      x => x.OnConsume(
         Arg<Banana>.Matches(
            y => object.ReferenceEquals(y, banana))));
}
即使已经处理了香蕉,

object.ReferenceEquals仍然有效,从而解决问题。