Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are strict and non-strict mocks?

Tags:

I have started using moq for mocking. Can someone explain me the concept of strict and non-strict mocks? How can they can be used in moq?

edit: in which scenario do we use which type of mock?

like image 237
Sandbox Avatar asked Jun 28 '10 16:06

Sandbox


People also ask

What is the difference between strict and loose mocking Behaviour?

When creating a mock, we can also give it strict or loose behavior. Strict behavior means that exceptions will be thrown if anything that was not set up on our interface is called. Loose behavior, on the other hand, does not throw exceptions in situations like this. Mocks, by default, are loose.

What is Mockbehavior strict?

Strict the mock behaves just like the object of the class you've mocked. It causes the mock to always throw an exception for invocations that don't have a corresponding expectation. Thus, if the you slightly changed the class (added a method), you'll also want to add that method to the mock to make your tests pass.

When should you not use mocks?

Only use a mock (or test double) “when testing things that cross the dependency inversion boundaries of the system” (per Bob Martin). If I truly need a test double, I go to the highest level in the class hierarchy diagram above that will get the job done. In other words, don't use a mock if a spy will do.

What is the difference between mocking and stubbing?

Stubbing, like mocking, means creating a stand-in, but a stub only mocks the behavior, but not the entire object. This is used when your implementation only interacts with a certain behavior of the object.


2 Answers

I'm not sure about moq specifically, but here's how strict mocks work in Rhino. I declare that I expect a call to foo.Bar on my object foo:

foo.Expect(f => f.Bar()).Returns(5);

If the calling code does

foo.Bar();

then I'm fine because the expectations are exactly met.

However, if the calling code is:

foo.Quux(12);
foo.Bar();

then my expectation failed because I did not explicitly expect a call to foo.Quux.

To summarize, a strict mock will fail immediately if anything differs from the expectations. On the other hand, a non-strict mock (or a stub) will gladly "ignore" the call to foo.Quux and it should return a default(T) for the return type T of foo.Quux.

The creator of Rhino recommends that you avoid strict mocks (and prefer stubs) because you generally don't want your test to fail when receiving an unexpected call as above. It makes refactoring your code much more difficult when you have to fix dozens of test that relied on the exact original behavior.

like image 105
Mark Rushakoff Avatar answered Sep 24 '22 10:09

Mark Rushakoff


Ever come across Given / When / Then?

  • Given a context
  • When I perform some events
  • Then an outcome should occur

This pattern appears in BDD's scenarios, and is also relevant for unit tests.

If you're setting up context, you're going to use the information which that context provides. For instance, if you're looking up something by Id, that's context. If it doesn't exist, the test won't run. In this case, you want to use a NiceMock or a Stub or whatever - Moq's default way of running.

If you want to verify an outcome, you can use Moq's verify. In this case, you want to record the relevant interactions. Fortunately, this is also Moq's default way of running. It won't complain if something happens that you weren't interested in for that test.

StrictMock is there for when you want no unexpected interactions to occur. It's how old-style mocking frameworks used to run. If you're doing BDD-style examples, you probably won't want this. It has a tendency to make tests a bit brittle and harder to read than if you separate the aspects of behaviour you're interested in. You have to set up expectations for both the context and the outcome, for all outcomes which will occur, regardless of whether they're of interest or not.

For instance, if you're testing a controller and mocking out both your validator and your repository, and you want to verify that you've saved your object, with a strict mock you also have to verify that you've validated the object first. I prefer to see those two aspects of behaviour in separate examples, because it makes it easier for me to understand the value and behaviour of the controller.

In the last four years I haven't found a single example which required the use of a strict mock - either it was an outcome I wanted to verify (even if I verify the number of times it's called) or a context for which I can tell if I respond correctly to the information provided. So in answer to your question:

  • non-strict mock: usually
  • strict mock: preferably never

NB: I am strongly biased towards BDD, so hard-core TDDers may disagree with me, and it will be right for the way that they are working.

like image 4
Lunivore Avatar answered Sep 25 '22 10:09

Lunivore