Moq, strict vs loose usage

34,985

Solution 1

I used to use strict mocks when I first starting using mocks in unit tests. This didn't last very long. There are really 2 reasons why I stopped doing this:

  1. The tests become brittle - With strict mocks you are asserting more than one thing, that the setup methods are called, AND that the other methods are not called. When you refactor the code the test often fails, even if what you are trying to test is still true.
  2. The tests are harder to read - You need to have a setup for every method that is called on the mock, even if it's not really related to what you want to test. When someone reads this test it's difficult for them to tell what is important for the test and what is just a side effect of the implementation.

Because of these I would strongly recommend using loose mocks in your unit tests.

Solution 2

I have background in C++/non-.NET development and I've been more into .NET recently so I had certain expectations when I was using Moq for the first time. I was trying to understand WTF was going on with my test and why the code I was testing was throwing a random exception instead of the Mock library telling me which function the code was trying to call. So I discovered I needed to turn on the Strict behaviour, which was perplexing- and then I came across this question which I saw had no ticked answer yet.

The Loose mode, and the fact that it is the default is insane. What on earth is the point of a Mock library that does something completely unpredictable that you haven't explicitly listed it should do?

I completely disagree with the points listed in the other answers in support of Loose mode. There is no good reason to use it and I wouldn't ever want to, ever. When writing a unit test I want to be certain what is going on - if I know a function needs to return a null, I'll make it return that. I want my tests to be brittle (in the ways that matter) so that I can fix them and add to the suite of test code the setup lines which are the explicit information that is describing to me exactly what my software will do.

The question is - is there a standard and normal way of doing this?

Yes - from the point of view of programming in general, i.e. other languages and outside the .NET world, you should use Strict always. Goodness knows why it isn't the default in Moq.

Solution 3

I have a simple convention:

  1. Use strict mocks when the system under test (SUT) is delegating the call to the underlying mocked layer without really modifying or applying any business logic to the arguments passed to itself.

  2. Use loose mocks when the SUT applies business logic to the arguments passed to itself and passes on some derived/modified values to the mocked layer.

For eg: Lets say we have database provider StudentDAL which has two methods:

Data access interface looks something like below:

public Student GetStudentById(int id);
public IList<Student> GetStudents(int ageFilter, int classId);

The implementation which consumes this DAL looks like below:

public Student FindStudent(int id)
{
   //StudentDAL dependency injected
   return StudentDAL.GetStudentById(id);
   //Use strict mock to test this
}
public IList<Student> GetStudentsForClass(StudentListRequest studentListRequest)
{
  //StudentDAL dependency injected
  //age filter is derived from the request and then passed on to the underlying layer
  int ageFilter = DateTime.Now.Year - studentListRequest.DateOfBirthFilter.Year;
  return StudentDAL.GetStudents(ageFilter , studentListRequest.ClassId)
  //Use loose mock and use verify api of MOQ to make sure that the age filter is correctly passed on.

}

Solution 4

Me personally, being new to mocking and Moq feel that starting off with Strict mode helps better understand of the innards and what's going on. "Loose" sometimes hides details and pass a test which a moq beginner may fail to see. Once you have your mocking skills down - Loose would probably be a lot more productive - like in this case saving a line with the "Setup" and just using "Verify" instead.

Share:
34,985
Bryan Rowe
Author by

Bryan Rowe

Updated on May 29, 2020

Comments

  • Bryan Rowe
    Bryan Rowe almost 4 years

    In the past, I have only used Rhino Mocks, with the typical strict mock. I am now working with Moq on a project and I am wondering about the proper usage.

    Let's assume that I have an object Foo with method Bar which calls a Bizz method on object Buzz.

    In my test, I want to verify that Bizz is called, therefore I feel there are two possible options:

    With a strict mock

    var mockBuzz= new Mock<IBuzz>(MockBehavior.Strict);
    mockBuzz.Setup(x => x.Bizz()); //test will fail if Bizz method not called
    foo.Buzz = mockBuzz
    foo.Bar();
    mockBuzz.VerifyAll();
    

    With a loose mock

    var mockBuzz= new Mock<IBuzz>();    
    foo.Buzz = mockBuzz
    foo.Bar();
    mockBuzz.Verify(x => x.Bizz()) //test will fail if Bizz method not called
    

    Is there a standard or normal way of doing this?

  • Daniel Lorenz
    Daniel Lorenz over 6 years
    I've been trying to figure out why people dislike Strict lately, too. The conclusion I have come to is that people who want to use Loose have a lot of public methods call other public methods in the same class. When this happens, you end up with class refactors that break all your tests even though you only want to focus on one particular method. That being said, to me, Loose mode = lazy because how can you even trust those tests are doing what you intend to do? What if the mocking defaults change in the future and they all break, anyway. With strict, that can't happen.
  • Daniel Lorenz
    Daniel Lorenz over 6 years
    Actually, this isn't even true. The only way strict becomes a problem is if your code isn't following SOLID. Otherwise, any changes you'd want your tests to break if the changes were that drastic.
  • Tibor Takács
    Tibor Takács over 4 years
    -1 This is exactly why strict mock is much better since it explicitly describes what happens with the dependencies. Verifying that one particular call happens is not meaningful if the same dependency object is triggered by many other unexpected calls. If the test becomes too complicated it is not the fault of strict mock but it is a good sign that either the code or test architecture has to be redesigned. Loose mock is a great tool for particular cases but this general statement that this answer suggests is counterproductive and against the test driven development principles.
  • granadaCoder
    granadaCoder over 4 years
    I agree, Strict should have been the default. Why do people dislike Strict. Because it is counter "easy peezey". Why would anyone turn on something (Loose) that makes finding the real issue harder? Because easyPeezey people don't care about quality. There is also the contractor mentality that likes more billable hours for these silly things. #hitANerve
  • Aldracor
    Aldracor almost 4 years
    @TiborTakács Uhm from what I read his experience is that using Srict is actually counterproductive with regards to TDD, in my experience aswell. I honestly don't see how you get to 'This is exactly why strict mock is much better' from this...
  • HappyTown
    HappyTown about 3 years
  • Paul Nogas
    Paul Nogas almost 3 years
    Although this discussion is pretty old, I feel that I need to add an silly example to help others that arrive here. Imagine OrderProcessor class with dependency on class Calculator. It has method getCost(itemCost, quantity). The unit test should not care if getCost calls Calculator.add(itemCost) quantity times or calls Calculator.add(Calculator.multiply(itemCost, quantity)). This is why loose is default and should be preferred. There are some times where Strict makes sense, but those are mainly the unfortunate times where you have non-pure functions that do side effects.