1

Please see the code below:

public class CreatePersonHandler
        : IRequestHandler<CreatePersonCommand,Unit>
    {

 public async Task<Unit> Handle(CreatePersonCommand message, CancellationToken cancellationToken)
        {
            var person = _enquiryFactory.Create(message.Gender, message.Salary);
            var offers = getAvailableOffers(); 
            person.AssignOffers(offers);
            await _mediator.DispatchDomainEventsAsync(person);
            return Unit.Value;
        }
  }

Notice that:

1) The command does not have any state.
2) The command method has no return value.

I have read a few similar questions on here e.g. this one: Unit testing void methods?. Are CQRS command handlers that return voids classed as informational and should not be unit tested?

dpapadopoulos
  • 1,834
  • 5
  • 23
  • 34
w0051977
  • 15,099
  • 32
  • 152
  • 329
  • 1
    It has side effects that you're probably interested in confirming, though. I'd think you want to check the events you expect are dispatched when this is executed. – Charles Mager Feb 15 '19 at 09:41
  • You should be able to mock and set expectations on your service interactions (Create, getAvailableOffers, AssignOffers) – ChrisBint Feb 15 '19 at 09:44
  • @Charles Mager/@ChrisBint, is it a bad idea to just have return true on the last line and have it return a bool. It would be so much easier. – w0051977 Feb 15 '19 at 09:58
  • What would testing that prove? The implementation could simply be `return true` and it'd still pass. – Charles Mager Feb 15 '19 at 09:59
  • @Charles Mager, I guess I would not mock the _mediator class? I would let the method call _mediator.DispatchDomainEventsAsync? – w0051977 Feb 15 '19 at 12:33

2 Answers2

3

Fundamentally, testing a "command handler" that returns a void is no different from testing a method that returns a void -- the void return is a clear indication that the method is invoked for its side effects, so you check for those.

Depending on the nature of the subject under test, it may make sense to use a test double, rather than a live collaborator, to determine whether or not the right thing happened.

var person = _enquiryFactory.Create(message.Gender, message.Salary);
var offers = getAvailableOffers(); 
person.AssignOffers(offers);
await _mediator.DispatchDomainEventsAsync(person);
return Unit.Value;

One thing to notice in this example is that, not only is there no state in your handler, but there is also no logic -- any branching here is encapsulated within the collaborators.

Assuming the pieces fit together, there's not a lot that can fail that is the responsibility of the handler. So I wouldn't block a pull request like this because there wasn't a "unit test" for the handler.

Could you clarify what you mean by: "Assuming the pieces fit together". I

In a "strongly typed" language, we would get a lot of checking done for us by the compiler/interpreter. If the type system isn't satisfied, then we are going to get an error message before the method is loaded into the execution environment.

VoiceOfUnreason
  • 52,766
  • 5
  • 49
  • 91
0

I see that you are adding/raising new events using .DispatchDomainEventsAsync(). Instead of returning nothing, you can return these events and write a simple unit test to count the number or structure these events.

Kanishk
  • 401
  • 3
  • 6