views:

72

answers:

3

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?

+1  A: 

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.

Grzenio
Thank you, that makes sense.
mxmissile
A: 

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.

jtsnake
+1  A: 

[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));
}
Dror Helper
Interesting. I'm currently using Rhino-Mocks for this project, I will definitely look into Typemock later on.
mxmissile