Question

I'm using Moq to test behaviour of some void methods. Using MockBehaviour.Strict every call to the mock must be specified during Arrange step. This is resulting in a lot of tests not having any Assert (or Verify) step. The pass condition is simply that the test ran without throwing an exception. Am I missing something? Is the Arrange, Act, Assert pattern unsuitable when using strict mocks? Is there a more semantic way to layout these tests?

A trivial made up example...

[TestClass]
public void DeleteUser_ShouldCallDeleteOnRepository()
{
    // Arrange
    var userRepository = new Mock<IUserRepository>(MockBehavior.Strict);

    int userId = 9;
    userRepository.Setup(x => x.Delete(userId));

    var controller = new UserController(userRepository.Object);

    // Act
    controller.DeleteUser(userId);

    // Assert
    // ...?
}
Was it helpful?

Solution

Your mock is taking the place of a collaborator. It's ideally doing one of two things:

  • Providing information or data
  • Doing a job

When the mock is providing information or data, it's enough that this should be a stub. You can set up the return value of the mock to the information required. This should be part of Arrange.

When the mock is doing a job, the delegation can be verified. This is why you have Assert.

What you're doing with the strict interaction is ensuring that every single interaction is expected, basically saying, "Here's what I expect to happen, and if anything else happens it's wrong." This is a different kind of testing to Act, Arrange, Assert, which says, "In this context, when I do this stuff, then I should get this outcome."

With a "nice" mock, you only need to worry about the interactions you're interested in. So, for instance, if I'm a controller and I'm looking up some information in one repository, validating it with a validator, then saving the result in another repository, I might have several tests:

  • one to check that I'm validating against the right information
  • one to check how I'm responding to incorrect validation
  • and one to check that I save the item.

With the strict mock, you have to do all the expectations, even if all you're interested in is the "save". By using a nice mock, we can split up the different aspects of behavior and only focus on one of them in each test.

As an additional bonus, nice mocks allow you to do:

  • Given a context
  • When this event happens
  • Then this outcome should occur

Whereas strict mocks make you do:

  • Given a context
  • Expect some stuff to happen
  • When I perform an event
  • Then go back and read what the outcome should have actually been.

The first of these is generally considered more readable.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top