Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it a test smell to mix in real implementation and mocks?

I have a consumer class responsible for consuming a string and deciding what to do with it. It can either parse and insert the parse data in a database or notify an administrator.

Below is my implementation.

public void Consume(string email)
{
    if(_emailValidator.IsLocate(email))
    {
        var parsedLocate = _parser.Parse(email);

        // Insert locate in database
    }
    else if(_emailValidator.IsGoodNightCall(email))
    {
        // Notify email notifying them that a locate email requires attention.
        _notifier.Notify();
    }
}

Below is my unit test.

// Arrange
var validator = new EmailValidator();
var parser = new Mock<IParser>();
var notifier = new Mock<INotifier>();
var consumer = new LocateConsumer(validator, parser.Object, notifier.Object);
var email = EmailLiterals.Locate;

// Act
consumer.Consume(email);

// Assert
parser.Verify(x => x.Parse(email), Times.Once());

Is it code smell to mix mocks and real implementation in unit tests? Also, how do always having to test whether method abc() always ran once? It doesn't seem right that once I add a new unit test every time I add a function inside my if block. Seems like if I continue adding to my Consume method I'm create a trap.

Thank you.

like image 212
Mike Avatar asked Mar 23 '11 18:03

Mike


People also ask

Are mocks a code smell?

Mock Objects are a Code Smell But mock objects are more often smelly because they are telling you something about the system under test. A Code Smell is defined as “a hint that something has gone wrong somewhere in your code”.

What is a test smell?

Test smells are defined as bad programming practices in unit test code (such as how test cases are organized, implemented and interact with each other) that indicate potential design problems in the test source code [3], [4], [5], [6].

What is test mocking?

What is mocking? Mocking is a process used in unit testing when the unit being tested has external dependencies. The purpose of mocking is to isolate and focus on the code being tested and not on the behavior or state of external dependencies.

When should you not use a mock?

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.


2 Answers

To be nitpicking, a unit test is an automated test that tests a unit in isolation. If you combine two or more units, it's not a unit test any more, it's an integration test.

However, depending on the type of units you integrate, having lots of that type of integration tests may be quite okay.

Krzysztof Kozmic recently wrote a blog post about this where he describes how Castle Windsor has very few unit tests, but lots of integration tests. AutoFixture also has a large share of those types of integration tests. I think the most important point is that as a general rule the integration must not cross library boundaries.

In any case you can view the actual implementation as an extreme end of the Test Double Continuum, so just as there are scenarios where it makes sense to use Stubs, Mocks, Spies, or Fakes, there are also scenarios where the actual implementation may make sense.

However, just keep in mind that you are no longer testing the unit in isolation, so you do introduce a coupling between the units that makes it more difficult to vary each independently.

To conclude, I still consider it a smell because it should always be an occasion to stop and think. However, a smell indicates no more than that, and sometimes, once you've thought it over, you can decide to move along.

like image 81
Mark Seemann Avatar answered Nov 14 '22 22:11

Mark Seemann


I would say a strong yes. Unit testing should be free of dependencies among components.

like image 24
Daniel A. White Avatar answered Nov 14 '22 21:11

Daniel A. White