2009-09-29 93 views
3

鉴于这种类:单元测试存根方法

public class OrderService 
{ 
    public OrderService(IOrderLogger log) 
    { 
     this.log = log; 
    } 

    private readonly IOrderLogger log; 

    public void PurgeOrder(Order order) 
    { 
     ... 

     var action = new LogAction("foo","bar"); 
     log.Action(action); 
    } 
} 

而且这个测试:

[Fact] 
public void PurgeOrder_should_log_action() 
{ 
    var order = new Order(); 
    var logger = MockRepository.GenerateStub<IOrderLogger>(); 
    var service = new OrderService(logger); 

    service.PurgeOrder(order); 

    logger.AssertWasCalled(x => x.Action(????)); 
} 

显然测试是错误的。如何在此场景中实际调用OrderLogger.Action(...)?如果LogAction在PurgeOrder方法内实例化,我不明白它是如何实现的。有什么建议么?

回答

1

您需要某种方式来比较LogActions。你可以在LogAction上实现Equals(如果从程序逻辑的角度来看是有意义的),或者实现一个比较器作为测试的一部分。在第一种情况下,您将创建与生产代码中相同的LogAction。

+0

谢谢你,这是有道理的。 – mxmissile 2009-09-29 20:36:11

0

我会用嘲弄,像EasyMock的,在那里你可以嘲笑IOrderLogger,然后做这样的事情:

IOrderLogger log = EasyMock.createMock(IOrderLogger.class); 
log.Action(EasyMock.isA(LogAction.class)); 
EasyMock.expectLastCall(); 

这假定操作()返回void。这是一个非常Java的方式。我不确定沿着EasyMock.net有多远。

1

[免责声明我在Typemock工作]

据我知道,可设定预期和验证方法的被称为是Typemock隔离的唯一工具。您正在寻找未来的被称为“未来的对象,”它有助于设定行为,并验证它们的对象,根据测试“将创建”里面的代码:

[Fact] 
public void PurgeOrder_should_log_action() 
{ 
    var order = new Order(); 
    var logger = Isolate.Fake.Instance<IOrderLogger>();  
    var logAction = Isolate.Fake.Instance<LogAction>(); 
    Isolate.Swap.NextInstance<LogAction>().With(logAction); 

    var service = new OrderService(logger); 
    service.PurgeOrder(order); 

    Isolate.Verify.WasCalledWithExactArguments(() => logger.Action(logAction)); 
} 
+1

有趣。我目前正在使用Rhino-Mocks来完成这个项目,稍后我肯定会研究Typemock。 – mxmissile 2009-09-29 20:36:44