mxmissile
mxmissile

Reputation: 11681

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? If the LogAction is instantiated inside the PurgeOrder method, I don't see how it's possible. Any suggestions?

Upvotes: 3

Views: 183

Answers (3)

Dror Helper
Dror Helper

Reputation: 30819

[Disclaimer I work at Typemock]

As far as I know the only tool that can set expectation and verify that method's were called is 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));
}

Upvotes: 1

jaketrent
jaketrent

Reputation: 1173

I would use mocks, something like EasyMock, where you could mock the IOrderLogger, and then do something like this:

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

This assumes that Action() returns void. This is a very Java-esque way of doing this. I'm not sure how far along the EasyMock.net has come.

Upvotes: 0

Grzenio
Grzenio

Reputation: 36679

You need some way to compare 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. In the first case you would create the same LogAction as in the production code.

Upvotes: 1

Related Questions