7

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.

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
Mike
  • 4,257
  • 3
  • 33
  • 47

3 Answers3

8

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.

Ruben Bartelink
  • 59,778
  • 26
  • 187
  • 249
Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
  • 2
    +1 mybe we should invent a new term **lightweight integratintest** or **nearly unittest** that combine just a few classes within a library as an acceptable-effort-tradeof-smell :-) – k3b Mar 23 '11 at 20:10
  • 1
    Yes, that was also my first thought as I read Krzysztof's post, but I've yet to come up with a good, catchy name. – Mark Seemann Mar 23 '11 at 20:20
  • +1 Great answer. While I agree with everything you said I'm not sure I quite follow when you say. I do agree that my test introduces coupling between modules. Short of using a container to wire up my modules in this test (which I'm not convinced is the best route to use) how do I avoid coupling? It seems rather inevitable. In the application itself it's not a problem because I wire everything up using Windsor and resolve my main object in the composition root (great article by the way). Only solution I can think of is to wire up my `Consumer` class in a set up method via poor man's DI. – Mike Mar 24 '11 at 14:32
  • 1
    If I understand the question correctly, perhaps this answer may be helpful to you: http://stackoverflow.com/questions/1465849/using-ioc-for-unittesting/1465896#1465896 – Mark Seemann Mar 24 '11 at 14:35
3

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

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
3
> Is it a test smell to mix in real implementation and mocks?

This is an integration test (combining 2 or more modules) and not a unittest (test one module in isolation)

My answer is No: I think it is ok to have mocks in integration test.

k3b
  • 14,517
  • 7
  • 53
  • 85
  • +1 However, I think the answer requires a little more elaboration, so I added my own thoughts as a separate answer. – Mark Seemann Mar 23 '11 at 19:43