Sponsored By Aspose - File Format APIs for .NET

Aspose are the market leader of .NET APIs for file business formats – natively work with DOCX, XLSX, PPT, PDF, MSG, MPP, images formats and many more!

Mocks are a code smell

Now that the title has grabbed your attention no I don’t really think that mocks are a code smell as a rule but I do think they are grossly overused and there are other ways of dealing with the same issues which should also be considered when designing  systems.

While not purely, I guess some may put me in the classicist camp ..

Ian Cooper has a great post up Classicist vs Mockist Test Driven Development. In the comments I have stated that I personally try to architect around a need for mocks in many cases and figured it a bit long to explain how in comments …

Let me say before I continue that these are not new ideas.

 Its not by accident that when you read old OOA/D books that they seem to use the concepts of “calling a method” on an object and “messaging an object” interchangeably. We can use this similarity to our advantage in our design … While the former requires me to mock the thing I am calling (you can’t call a method on a non-existent object) the latter if I introduce a dispatcher does not need to have an object that it is targeting. As we will also see this method also tends to remove  move the need for dependency injection.

Naive Example

I never understand things unless they are shown to me in code so let’s imagine the canonical example of an ATM with a controller and various services it interacts with. This makes a great example as it has a few services that it would orchestrate (generally 1-2 per test). These scenarios are also almost exclusively request/response which is very common in most of our object interactions (especially with services) making a 1-way call an asynchronous message is rather trivial to do and is a no-brainer for nearly ‘ility we could possibly discuss.

Let’s start with the first stage of coming to an ATM machine. I put in my card and then expect it to ask me to authenticate (yes it usually asks me for a pin but maybe its a fancy-shiny-new-atm that uses biometrics so we will assume there are multiple interchangeable mechanisms).

In a mocking scenario we would have a few tests here using mocks. The first test would be in the ICardReaderService implementation where we would mock the HAL (Hardware Abstraction Layer) and insure that our expectation of it receiving a message and appropriately calling a mock of our ATMController is met.

Further we would have tests to insure our expectations of the controller properly calling the IAuthenticationService when it is notified that a card has been placed in the ATM. note that we could have the services call each other directly but generally a controller is a preferred pattern.

Have you noticed in visualizing these tests that almost all of our code is setting up mocks and expectations for our tests? What if we were to model this so instead of being direct method calls all of these items were done through messages and handled by Finite State Machines?

 

First we will need some concept of what exactly a message is. I am providing a naive example for the sake of this post.

public interface IMessage {     
IMessageConsumer Sender { get ; }
}

public interface IBidirectionalMessage : IMessage
{
IMessageConsumer Sender { get; }
void ReplyWith(IMessage Reply);
}

Second we will need some way of having our messages sent between the objects, in a real system we would like use a message dispatcher that supports all sorts of neat and fun things but in testing we don’t actually want them dispatched (we only care that they actually were created its for our integration tests to insure that they actually get dispatched appropriately) so we can come up with a pretty dumb implementation of our dispatcher …

public interface IMessagePublisher   
{
void Publish(IMessage message);
}


public class FakeMessagePublisher : IMessagePublisher
{
private Queue messages;
public FakeMessagePublisher()
{
messages = new Queue();
}
public void Publish(IMessage message)
{
messages.Enqueue(message);
}
public IEnumerable AllMessages()
{
while (messages.Count > 0) {
yield return messages.Dequeue();
}
}
}

To make things complete we will also need to bring in our IMessageConsumer interface which is used above. Non-naive versions of these interfaces and the dispatcher could probably have books written about them so please forgive the naivity of the examples.

If you want to take a look at a nice implementation of similar ideas take a look at nServiceBus though if you are working on smaller applications you may find this to be a rather large dependency, a simple stripped down in-process dispatcher is a very easy piece of code to write.

public interface IMessageConsumer  
{
void ConsumeMessage(IMessage Message);
bool CanConsume();
}

Then we will create a simple static locator that everything can use to find the current messaging subsystem (yes DI is a good thing here but when we only have 1 thing to inject do we care?).

Once we have this class we can start working on our actual system and write some tests.

So our first test identified was to insure that the CardReaderService actually notifies the IATMController that a card has been placed in the reader.  We will need a message for it to use to do the notification.

class CardInsertedMessage   
{
public readonly string CardHolder;
public readonly string CardNumber;

public CardInsertedMessage(string cardHolder, string cardNumber)
{
CardNumber = cardNumber;
CardHolder = cardHolder;
}
}

Now we can write our first test using a Fake for the HAL (which btw is one place I always agree with using a fake).

[Test]  
public void Reader_ShouldSendCardInsertedMessage_When_CardInserted()
{
ICardReaderHAL FakeHAL = new FakeCardReaderHAL();
IATMCardReaderService CardReader = new ATMCardReaderService(FakeHAL);
FakeHAL.InsertCard("1111 1111 1111 1111", "Greg Young");
List messages = new List(FakeMessagePublisher.AllMessages());
Assert.AreEqual(1, messages.Count);
Assert.IsType(messages[0]);
CardInsertedMessage message = (CardInsertedMessage) message[0];
Assert.AreEqual("Greg Young", message.CardHolder);
Assert.AreEqual("1111111111111111", message.CardNumber);
}

Notice that we don’t care here about the handling of the message? We only care that the message was created! This is very much the way that mocking works no? Our expectation is not that some other object was called but simply that the message was raised from this object. We will later test in integration tests that things do actually happen.

One thing I will also point out is that we don’t have any mock setup for expectations that could deviate from how our actual objects work.

So now let’s go to our next test, that the controller properly handles the fact that a card was inserted and asks the authentication service to authenticate us and that once it sends the request it is capable of receiving the response.

public void Controller_ShouldRequestAuthentication_When_CardInsertedMessageReceived()  
{
ATMController Controller = New.ATMController.InState(ATMController.States.AwaitingCard);
CardInsertedMessage InsertedMessage = new CardInsertedMessage("Greg Young", "11111111111111");
controller.ConsumeMessage(InsertedMessage);
List messages = new List(FakeMessagePublisher.AllMessages());
Assert.AreEqual(1, messages.Count);
Assert.IsType(messages[0]);
Assert.AreEqual(Controller, request.Sender);
Assert.IsTrue(Controller.CanAccept());
}

Dual Expectations?

In our Controller_ShouldRequestAuthentication_When_CardInsertedMessageReceived test the astute reader may hold an objection to the test actually testing two expectations. The first expectation being that the controller properly generated a message and the second expectation being that the controller was able to receive the expect response to the message. To be honest I am on the fence with this one, on one hand the expectations are very closely linked to each other, on the other hand they are very different expectations. I personally tend to put the two expectations into one test because if either fails it still gets me close enough to the point where things are failing that I can quickly solve the problem but mileage may vary for others. If people find it to be more correct, here are the seperated versions of the tests.

public void Controller_ShouldRequestAuthentication_When_CardInsertedMessageReceived()  
{
ATMController Controller = New.ATMController.InState(ATMController.States.AwaitingCard);
CardInsertedMessage InsertedMessage = new CardInsertedMessage("Greg Young", "11111111111111");
controller.ConsumeMessage(InsertedMessage);
List messages = new List(FakeMessageDispatcher.AllMessages());
Assert.AreEqual(1, messages.Count);
Assert.IsType(messages[0]);
Assert.AreEqual(Controller, request.Sender);
}

public void Controller_ExpectsAuthenticationResponse_After_SendingAuthenticationRequest()
{
ATMController Controller = new ATMController();
CardInsertedMessage InsertedMessage = new CardInsertedMessage("Greg Young", "11111111111111");
controller.ConsumeMessage(InsertedMessage);
Assert.IsTrue(Controller.CanAccept());
}

The tests for the IAuthenticationService and the handling of the return message to the controller are almost identical to these tests. Due to these similarities I am going to skip ahead to the final part of the process; a naive example of giving the customer money. As before we will need a message

class DispenseMoneyMessage  
{
public readonly decimal Amount;
public DispenseMoneyMessage(decimal amount)
{ Amount = amount;
}
}

Now the part that is different with our pretend ATM is that the CashHopperService has a state in it of how much money is left in the machine. So we can write a test for how much money is in the ATM.

Now we can implement our test.

public void CashHopperService_ShouldUpdateAmountOfCash_WhenItDispensesCash()  
{
FakeHopperHAL FakeHAL = new FakeHopperHAL();
CashHopperService hopper = new CashHopperService(FakeHAL);
FakeHAL.AddCash(5000.00m);
hopper.ConsumeMessage(new DispenseCashMessage(500.00m));
Assert.IsEmpty(FakeMessagePublisher.AllMessages());
Assert.IsEqual(4500.00, hopper.CashAvailable);
}

The Testing Threesome

I said before I that I skipped many of the interactions because the were uninteresting. This is because there are EXACTLY THREE TYPES OF TESTS WE WILL EVER WRITE. In the examples above we covered all three.

  • Message-Is-Produced-When-An-External-Event-Occurs
  • Message-Produced-When-A-Message-Is-Consumed
  • State-Is-Transitioned-When-A-Message-Is-Consumed

That’s it! Given that we only have these types of tests and all of them are extremely similar we can quite easily come through and use my other favorite programming threesome Reduce, Recycle, Reuse!

It doesn’t take much imagination to see something like this in our not so distant future.

public void Controller_ShouldRequestAuthentication_When_CardInsertedMessageReceived()  
{
When.Consumer<ATMController>().InState(ATMController.States.AwaitingCard)).
Receives(Fakes.CardInsertedMessage).
Expect<AuthenticationRequest>();
}

With an API like this why are we even naming our tests?!

We could even take this very quickly to a metadata based method of testing. There are MANY well known ways of easily testing state machines (and generating them from metadata descriptions of them which might be in a DSL).

Dependency Eradication

There has been ALOT of talk lately about dependency injection and all of the issues that can go along with it. Of late there was one particular thread on the altdotnet list AMC: Changes the way we think which is of interest.

Village Wisdom:

–          We use constructor dependency injection (and sometimes properties) because it’s important to expose your dependencies…

–          … so that callers who aren’t using IoC (ahem  tests) can easily work with the test in isolation by using mocks and not having to involve an IoC container…

–          … and so it behooves us to keep the number of dependencies in a class down to a minimum to keep tests from getting too complicated…

–          … which also forces us to battle between too-many-dependencies and dependencies-that-do-too-much.

Basically, it seems like we make a lot of choices based on writing tests and the fact that our tests don’t use IoC (to keep things less complicated, we tell ourselves).

Well I am going to disagree strongly with #1. I think an object is much better to have NO dependencies than to expose them. In the canonical example of sending an email why does the object need to even care that there is an email service which actually sends the email?

“Changing the way we think…” is what’s really needed here … walk away from doing EVERYTHING as direct object interations and move to decoupling through messaging!

Or to comment to Roy Osherove’s post who ever said testability has to lead to dependency injection?! Given these posts lead to type mock but …

Others have even gone so far as to make the fallacious statement that Domain Driven Design is not possible without DI and AOP but this deserves a long post on its own.

This is not to say that messaging is built on a system of Love and Rainbows.

Trouble in Paradise?

Are you thinking to yourself

‘sure this is great in the success cases but what about the failures?’

Well umm yeah it can be a problem and a quick blog post is definitely not the place to address all of these issues. The big issue here is that since we are using messages for our interactions we may or may not have a call stack. Without a call stack exceptions as they exist in the framework well don’t work.

There are a few cases that can be problematic with exceptions. The first is when dealing with a bi-directional message. When we send a request the processor gets an exception and fails. The processor (or in some implementations the dispatcher can) package up an exception message with the details of the message and return the results instead of the success response (a common pattern for this might also be to make the response support being a failure and including the exception).

The next case which is particularly nasty is when you are dealing with a one way message. What happens when the thing processing it on the other side fails? Depending on the situation this may be very problematic because if the message is say a delta message there is a real possibility that the component will not be able to process any more messages (possibly inconsistent state).

The last case that can be extremely problematic is when you have a request/response based message and either your message doesn’t actually get routed anywhere or whatever was processing it on the other side died. Without someway of gracefully handling this your object will sit in its waiting on response state forever.

 

This difference in thinking of course does open us up to being able to distribute our objects fairly transparently to multiple processes and/or machines

 

Balancing the Scale

Since NOTHING has a reference to anything except for the dispatcher and our messages as objects are easily serializable we can quite easily move them out of our own process even to a processor running on a wrist-watch in Russia if we liked without our system knowing or really caring that we did that.

This does not bypass the old RPC should not be transparent thought as you still should be THINKING about the overhead involved.

 

The second large scalability gain is that we can quite easily multi-thread. Our threading boundaries are not decided within our code but in how we dispatch our messages.

 

Basically while a messaging based system may start out running a very simple model you can scale it by changing how you dispatch and process messages.

 

Conclusion

If there is one thing to quote from here it is this:

Messaging is not for EVERYWHERE but its a tool that should be in your toolkit. Each side has its pros and cons but right now everyone seems so focused on things like IOC containers and mocking frameworks that they have completely forgotten that its sometimes best to not have a dependency at all.

I personally like to keep a rule that I call methods inside of an aggregate root but as soon as I leave the aggregate root I use a message.

I know this has been a long read; but I am barely even scratching the surface of everything I want to say on this subject. I would love to go into further discussions like

“How do you actually implement that dispatcher thing?”

“How do you make that dispatcher thing work with multiple machines?”

“You mean somebody already implemented that dispatcher thing for me?”

“How do we make that fluent interface we saw”

“How do messaging and Domain Driven Design interact”

“Messaging, Pipelines, and Interception”

“What is the pi-calculus and why do I care?”

But even writing this takes quite a bit. What if any of those continuations sound good?

This entry was posted in DDD, DDDD, Featured, Messaging, mock, pi-calculus, TDD. Bookmark the permalink. Follow any comments here with the RSS feed for this post.

20 Responses to Mocks are a code smell

  1. Hi Greg,
    Roger – NAspect / NPersist here, its been quite a while since we spoke.

    Im really interested in your oppinion on this:

    >>Others have even gone so far as to make the fallacious statement that Domain Driven Design is not
    >>possible without DI and AOP but this deserves a long post on its own.

    While I might not go so far to say that you can’t do DDD w/o DI and AOP, but it certainly helps and the ideas that he present in that movie is the way to go IMO.

    So any chance you could elaborate on that one? or even go for that “long post of its own”? 😉

  2. Greg says:

    Yes udi they are handled by sagas …

    per nservicebus I am referring to a rather specific case of doing very lightweight dispatching (think in process dispatch by message type) where you can write about 20 lines of code to handle things and avoid external dependencies.

    As I said the example was a naive one :)

  3. Udi Dahan says:

    I was wondering why you consider the dependency on nServiceBus to be so heavy. Service layer code will depend on nServiceBus.dll – which just contains 3-4 interfaces and a couple of structure-classes. All the actual infrastructure – msmq, etc, is xcopied and configured in.

    You might want to take your in-memory queue and implement ITransport around it.

    As for all the failure scenarios you mentioned, those are primarily handled by sagas.

  4. Jimmy Bogard says:

    I wouldn’t call this an argument against mocks. It’s really an argument against transparent dependencies. Messaging decouples two dependencies, but like the other commenter mentioned, it’s a tradeoff.

    Additionally, what TDD’ers are saying is not that IoC is mandatory, but the dependency inversion principle is. To test a component/class in isolation, it cannot interact with other external dependencies. Traditionally this has meant file system, network, database, etc. With DDD in the mix, this has meant any Service in your model.

    DIP doesn’t automatically require IoC containers. In one project I was on, we followed the DIP throughout our entire codebase but never once introduced Spring, StructureMap, Windsor, or the like. We just designed against interfaces for our services. Calling code would put the correct dependency in, whether through constructors, builders, factories, etc.

    It’s a straw man argument to say that transparent dependencies/dependency injection requires mocking to test. The selection of the test double depends on what you’re testing. If you’re testing interactions between two classes, mocks are the way to go. But you still have stubs, fakes and dummies to look at. The mistake with folks doing DIP is to rely on mocks for all of their test doubles, when they really want one of the others. But nothing in the DIP says “you must use mocks for test doubles”.

  5. Greg says:

    yes Colin it fits as a TestSpy well …

  6. Colin Jack says:

    @Greg
    Would this definition not cover it: http://xunitpatterns.com/Test%20Spy.html

    I’d also be interesting in knowing how the IMessageProducer interface fits into it all, but I guess thats part of the other post.

  7. Greg says:

    Nat: an even better link on why I don’t think those are mocks martinfowler.com/…/mocksArentStubs.html

     

    but by this definition I should be calling it a Stub I guess since it does record information. 

  8. Greg says:

    Nat:
    I wouldn’t call the fakedispatcher a mock, I would call it a fake.

    From wikipedia:
    Mocks and fakes

    Fakes are the simpler of the two, simply implementing the same interface as the object that they represent and returning pre-arranged responses. Mock objects in this sense do a little more: their method implementations contain assertions of their own. This means that a true mock, in this sense, will examine the context of each call—perhaps checking the order in which its methods are called, perhaps performing tests on the data passed into the method calls as arguments.

    My Fake has no expectations in it … it is just a bucket. The expectations live in the test.

    Nat and Chad:

    Per exporting dependencies … I will write up a post showing this… For in process dispatching this can actually be done with compile time support using code generation and by making the producer/consumers generic. This not only exports what the object does out of the object but also allows for pretty much everything that DI does. The one issue with this is that it will only work when you are dealing in-process with single dispatch.

    In particular to how I would address visibility, it is easily discoverable that my ATMController implements the IMessageProducer interface from the outside.

    Nat:
    I understand 100% that there is a trade off here … as I said in the post

    “Messaging is not for EVERYWHERE but its a tool that should be in your toolkit. Each side has its pros and cons but right now everyone seems so focused on things like IOC containers and mocking frameworks that they have completely forgotten that its sometimes best to not have a dependency at all.”

  9. Colin Jack says:

    Somethings gone wrong with the formatting on my comment so I thought I’d try again…

    @Nat
    On the mocking I don’t necessarily agree, as I understand it the tests now use a simple Test Spy class which is registered once with the static locator. This does make testing much easier (it’s an approach I use and really like).

    On the collaborators front my views are guided by the fact that I don’t think that I need to see all of a classes dependencies on its interface. Collaborators are important but seeing class A collaborates with B doesn’t necessarily tell us enough about that interaction to be able to know about the behavior of A, I’ll always need to look at the usage to see that.

    There are also different styles of collaboration. I use something similiar to the style Greg suggests for situations where my domain classes talk to pure infrastructure (dirty tracking), but I haven’t gone as far as to use it for cross aggregate communication. Needless to say I don’t use DI with domain entities anyway though.

    On the little language bit, could you give an example because although I think I know what you mean I could be misunderstanding.

    @Greg
    Really interesting article, good stuff and as you guess I’m sure its gonna spark some interesting debate :)

    For me the most interesting follow ups would be:
    “How do messaging and Domain Driven Design interact?”
    “How do you actually implement that dispatcher thing?”
    “How do I handle return values and/or updating state within my domain entities?”

  10. Colin Jack says:

    @Nat
    On the mocking I don’t necessarily agree, as I understand it the tests now use a simple Test Spy class which is registered once with the static locator. This does make testing much easier (it’s an approach I use and really like).

    On the collaborators front my views are guided by the fact that I don’t think that I need to see all of a classes dependencies on its interface. Collaborators are important but seeing class A collaborates with B doesn’t necessarily tell us enough about that interaction to be able to know about the behavior of A, I’ll always need to look at the usage to see that.

    There are also different styles of collaboration. I use something similiar to the style Greg suggests for situations where my domain classes talk to pure infrastructure (dirty tracking), but I haven’t gone as far as to use it for cross aggregate communication. Needless to say I don’t use DI with domain entities anyway though.

    On the little language bit, could you give an example because although I think I know what you mean I could be misunderstanding.

    @Greg
    Really interesting article, good stuff and as you guess I’m sure its gonna spark some interesting debate :)

    For me the most interesting follow ups would be:

    “How do messaging and Domain Driven Design interact?”
    “How do you actually implement that dispatcher thing?”
    “How do I handle return values and/or updating state within my domain entities?”

  11. Robin Clowers says:

    This is a really interesting concept, I would definitely like to see some follow up posts.

  12. Justice~! says:

    This is a great post. I don’t normally just add a “me too” in my comments but I think a lot of this is preaching to the choir for me. As much I feel mocking is useful I definitely do find it overused in cases where there are simpler ways to still run the same tests.

  13. Rob says:

    Great post. I’m always interested in different approaches to solving problems. I’d love to see you take this further with some of the discussions you mentioned.

  14. Chad Myers says:

    Greg, one of the main arguments on the mailing list was that it is important to have all your dependencies exposed (usually via the ctor) as this increases something or other (I won’t try to make their argument for them). This seems ‘nice’, but I’m not sold as to how valuable this practice really is.

    It seems that in your examples, the types of messages a service would receive or send out is not immediately obvious to an outside observer.

    How would you address the ‘dependency visibility’ critics?

  15. Tim B says:

    Greg your code snippets are all jacked because HTML isn’t interpreted inside the tags.

  16. Aaron Jensen says:

    Greg, your code snippets are totally broken in browser. (br’s show and there’s no new lines.)

  17. Gregory says:

    “How do messaging and Domain Driven Design interact” and “Messaging, Pipelines, and Interception” sound the most interesting to me. You haven’t convinced me, but I’m listening . . .

  18. Nat says:

    You have neither removed mocks nor eliminated dependencies. The way you are testing how your objects are sending messages via a fake dispatcher *is* a mock object. You have mocked out the dispatcher. And objects do have dependencies on one another, its just that they are hidden by the dispatcher and have to be understood by reading the imperative code of all the message consumers instead of declarative code that connects objects together.

    Multicasting events is not a replacement for directly introducing objects to one another. It’s a trade off. It’s a big help when objects are frequently, dynamically added to or removed from the system because there is less explicit wiring to modify. But that benefit comes at the price that it is harder to understand the runtime dependencies between objects: that explicit wiring helps people understand the architecture of the code.

    It also limits your ability to raise the level of abstraction. The code that connects objects is, itself, a little-language that expresses what the composition of objects does. And that little-language is then used to build up to another little-language at an even higher level of abstraction. And so on until the “top” of the system is a short, declarative description of what the entire system does.

  19. Miika says:

    This is interesting. Being new to messaging concepts, some ideas where to read more?

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>