CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Greg Young [MVP]

February 2008 - Posts

  • 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?

  • Alt.Net Seattle

    Unfortunately I was at lunch so Dave beat me to it but  Registration is open ... only about 100 seats first come first serve and there are some amazing people coming already. There will be some awesome future looking discussions put up including I think some about spec#!

     
    Hope to see you there.

     

  • Irony!!


    Been looking for something like this ... This will be quite useful for things like DSL creation or for finally creating that logo.net implementation we have all been waiting for.

     
    Or you could for instance start putting serialized versions of ASTs in attributes anyone? Think ...

     


    private void MyMethod( [Requires("value>5 and value<10")] int i) {
    }

    I reckon you could implement that in a few hours with this little gem. ASTs in attributes are yummy.

    http://www.codeplex.com/irony
     

    using System;
    using System.Collections.Generic;
    using System.Text;
    using Irony.Compiler;

    namespace Irony.Samples {
    //Sample expression grammar - recognizes arithmetic expressions with numbers and variables
    //
    // Expr -> n | v | Expr BinOp Expr | UnOp Expr | ( Expr )
    // BinOp -> + | - | * | / | **
    // UnOp -> -
    // ExprLine -> Expr EOF

    public class ExpressionGrammar : Irony.Compiler.Grammar {
    public ExpressionGrammar() {
    // 1. Terminals
    Terminal n = new NumberTerminal("number");
    Terminal v = new IdentifierTerminal("variable");

    // 2. Non-terminals
    NonTerminal Expr = new NonTerminal("Expr");
    NonTerminal BinOp = new NonTerminal("BinOp");
    NonTerminal UnOp = new NonTerminal("UnOp");
    NonTerminal ExprLine = new NonTerminal("ExprLine");

    // 3. BNF rules
    Expr.Rule = n | v | Expr + BinOp + Expr | UnOp + Expr | "(" + Expr + ")";
    BinOp.Rule = Symbol("+") | "-" | "*" | "/" | "**";
    UnOp.Rule = "-";
    ExprLine.Rule = Expr + Eof; //EOF it is optional
    this.Root = ExprLine; // Set grammar root

    // 4. Operators precedence
    RegisterOperators(1, "+", "-");
    RegisterOperators(2, "*", "/");
    RegisterOperators(3, Associativity.Right, "**");

    PunctuationSymbols.AddRange(new string[] { "(", ")" });

    }
    }
    }

    // Parsing expressions
    ExpressionGrammar grammar = new ExpressionGrammar();
    LanguageCompiler compiler = new LanguageCompiler(grammar);

    string expr = "a + b * 3.14 / (2.0 * x + y**z**2)";
    AstNode rootNode = compiler.Parse(expr);
    //rootNode now contains an AST node that is the root of the syntax tree.
     
    updated: nice little article here http://www.codeproject.com/KB/recipes/Irony.aspx

  • DbC and Iterators

    For those who have never been in one of my spec# talks one of the largest benefits I like to tout about spec# is that it offers the possibility of removing runtime checks through the use of static verification.

     If I have proven that a condition could never possibly fail and that all of my code is covered by the prover why on earth would I need to emit runtime code other than to test that the prover was correct?


    While not sounding like a huge benefit this would be one of the largest performance benefits of recent times as all validation code could feasibly be removed from runtime execution (pipelines are still small and branches can be expensive).

    There is however one area which I have recently run into where this is not the case.

           static void RequiresValueOfFive(int val, string! str)
                requires val == 5;
           {
               Console.WriteLine(val.ToString() + " " + str);
           }

           static IEnumerable<string!>! YieldGetIEnumerable()
               ensures Foo == 5 ;
           {
               yield return "test";
               Foo = 5;
               yield return "test2";
           }

           static IEnumerable<string!>! GetIEnumerable()
           ensures Foo == 5 ;
           {
               List<string!> ret = new List<string!>();
               ret.Add("test");
               ret.Add("test2");
               Foo = 5;
               return ret;
           }
     
    then …

           Foo = 0;
           IEnumerable<string!> somethingelse = YieldGetIEnumerable();
           foreach(string! s in somethingelse) {
             RequiresValueOfFive(Foo, s);
            }
    In this example there is a significant difference between the way that iterators and a normal IEnumerable<T> work with post-conditions; iterators are a leaky abstraction. While it is not a big deal to change your code to handle these circumstances the spec# compiler does not know how to deal with them during proving.

    At the outset this may not seem like too big of a deal but what happens when I decide to refactor from the first case to the second? All of my code will still compile, still run, but will fail with runtime assertions. Unless the compiler becomes smart enough to move the post-condition to the MoveNext (when it returns false) this nullifies the hope of removing runtime checks in a purely statically validated environment. Even with this change, I believe there are still runtime failures that can occur.

    Given this information are iterators something that are THAT desirable? Iterators are syntactical sugar, I can duplicate what an iterator does rather simply in code that does not use an iterator … Are they worth me giving up the possibility of removing all of my runtime checks or introducing this complexity?

     

    Note to self: check out how JML approaches this.
     

More Posts