简体   繁体   English

单元测试存根方法

[英]Unit Testing Stubbed Method

Given this class: 鉴于此类:

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

And this test: 而这个测试:

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

Obviously the test is wrong. 显然测试是错误的。 How can I assert the OrderLogger.Action(...) was actually called in this scenario? 如何在这种情况下断言OrderLogger.Action(...)? If the LogAction is instantiated inside the PurgeOrder method, I don't see how it's possible. 如果LogAction在PurgeOrder方法中实例化,我看不出它是如何可能的。 Any suggestions? 有什么建议么?

You need some way to compare LogActions. 您需要一些方法来比较LogActions。 You can either implement Equals on LogAction (if it makes sense from the program logic point of view), or implement a comparer as part of the tests. 您可以在LogAction上实现Equals(如果从程序逻辑的角度来看是有意义的话),或者将比较器作为测试的一部分来实现。 In the first case you would create the same LogAction as in the production code. 在第一种情况下,您将创建与生产代码中相同的LogAction。

[Disclaimer I work at Typemock ] [免责声明我在Typemock工作]

As far as I know the only tool that can set expectation and verify that method's were called is Typemock Isolator. 据我所知,唯一可以设置期望并验证方法被调用的工具是Typemock Isolator。 The future you're looking for is called "future objects" it helps set behavior and verify them on objects that "will be created" inside the code under test: 您正在寻找的未来被称为“未来对象”,它有助于设置行为并在被测试代码中“将被创建”的对象上验证它们:

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

I would use mocks, something like EasyMock, where you could mock the IOrderLogger, and then do something like this: 我会使用类似EasyMock的模拟,你可以模拟IOrderLogger,然后执行以下操作:

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

This assumes that Action() returns void. 这假设Action()返回void。 This is a very Java-esque way of doing this. 这是一种非常Java的方式。 I'm not sure how far along the EasyMock.net has come. 我不确定EasyMock.net到底有多远。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM