我有一个看起来有点像这样的测试(我正在简化我的实际问题):
[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}}被调用,这会导致测试失败。解决这个问题的最佳方法是什么?
答案 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)
几种可能的解决方案:
答案 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
仍然有效,从而解决问题。