Thanks a lot for the example. I don't think When..Do will work here; we can't set the return value from there and it will still get called all the time too.
I realise this may not fit in with the larger context, but maybe it would help to separate the details about how `_tradeServer.Trade()` works and just use the contract behind the interface? Something like, "
when `Trade()` is called it will return a Success report or a Failure report". (Specific details like "
the success report will include the order and quote passed as arguments" can possibly be deferred to the tests for the trade service, but the calling code may not need to know that detail)
The test would then look more like this:
_tradeService.Trade(null, null, default(DateTime)).ReturnsForAnyArgs(_successfulReport);
where `_successfulReport` is a pre-canned result from `ExecutionReport.Success()`, or a directly constructed object, or a mocked successful report. I guess this depends on how the calling code needs to use the report, but hopefully it won't need to know anything about how trade service works, only how to handle a successful report. (If it does need to know this detail, can we use a real TradeService here instead of a mocked one? Maybe we can mock the boundary a bit further out instead?)
Because we've conveniently ignored the detail of how the arguments are linked to the output, we can now override this `Returns` in the other test without a problem.
Another approach could be a variation on the closure-cheat-hack-yuck suggestion:
//Field in test fixture:
Func<ICallInfo,ExecutionReport> _getReport;
//Test setup:
_getReport = call => ExecutionReport.Success(call.Arg<NewOrderRequest>, call.Arg<IFxQuote>);
_tradeService.Trade(null, null, default(DateTime)).ReturnsForAnyArgs(call => _getReport(call));
//Other test that overrides the result:
_getReport = call => ExecutionReport.Failure();
...
Now we can reassign the `_getReport` delegate to change what `_tradeService.Trade()` returns (without having to use NSub to alter the `Returns`). Bit yuck I admit, but should work ok here.
Alternatively we could make the initial delegate code from your example handle the null case (more hacking around the NSub limitation). But I'm already scraping the bottom of the barrel so I'll stop here. :)
Hope some of this rambling helps. If not let me know and I'll try and come up with some other ideas tomorrow once I've slept on it. :)