Mockito-Flex meets ASUnit

Well, that’s not a catchy headline, but it does pretty much sum it up. I’ve been playing with Mockito-Flex, a mock object framework for Actionscript 3. It’s great, and made vastly easier to pick up by a Mockito-FlexUnit bridge in the form of a MockitoTestCase that does the hard work of reporting the mocking results and validations in a way that FlexUnit can display.

Of course, FlexUnit does require the Flex framework, which bulks up the whole thing. Oh, and I’m used to using ASUnit. So I’ve written the following class that does the same job as MockitoTestCase, but for ASUnit:

  1. /**
  2.  * The MIT License
  3.  *
  4.  * Copyright (c) 2009 Mockito contributors
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
  7.  * and associated documentation files (the "Software"), to deal in the Software without restriction,
  8.  * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9.  * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
  10.  * subject to the following conditions:
  11.  *
  12.  * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
  13.  *
  14.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
  15.  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
  16.  * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  17.  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18.  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  19.  */
  20.  
  21. package org.mockito {
  22.     import asunit.framework.TestCase;
  23.  
  24.     import org.mockito.api.Matcher;
  25.     import org.mockito.api.MethodSelector;
  26.     import org.mockito.api.MockCreator;
  27.     import org.mockito.api.Stubber;
  28.     import org.mockito.api.Verifier;
  29.  
  30.    
  31.     public class ASUnitMockitoTestCase extends TestCase {
  32.  
  33.         private var _mockClasses:Array;
  34.  
  35.         protected var mockito:Mockito;
  36.        
  37.         public function ASUnitMockitoTestCase(mockClasses:Array, testMethod:String = null)
  38.         {
  39.             _mockClasses = mockClasses;
  40.             super(testMethod);
  41.         }
  42.  
  43.         /**
  44.          * Due to the asynchronous nature of the class generation
  45.          * a test needs to execute from a callback function
  46.          */
  47.         public override function run():void
  48.         {
  49.             if (mockito == null && _mockClasses)
  50.             {
  51.                 mockito = new Mockito();
  52.                 var superRun:Function = super.run;
  53.                 mockito.prepareClasses(_mockClasses, repositoryPreparedHandler);
  54.                 function repositoryPreparedHandler():void
  55.                 {
  56.                     superRun();
  57.                 }
  58.             }
  59.             else
  60.             {
  61.                 super.run();
  62.             }
  63.         }
  64.        
  65.        
  66.  
  67.         /**
  68.          * Constructs mock object
  69.          * @param clazz a class of the mock object
  70.          * @param constructorArgs constructor arguments required to create mock instance
  71.          * @param name a name used in various output
  72.          * @return a mocked object
  73.          */
  74.         public function mock(classToMock:Class, name:String = null, constructorArgs:Array = null):Object
  75.         {
  76.             return mockito.mock(classToMock, name, constructorArgs);
  77.         }
  78.  
  79.         /**
  80.          * A starter function for verification of executions
  81.          * If you dont specify the verifier, an equivalent of times(1) is used.
  82.          * @param verifier object responsible for verification of the following execution
  83.          */
  84.         public function verify(verifier:Verifier = null):MethodSelector
  85.         {
  86.             return mockito.verify(verifier);
  87.         }
  88.  
  89.         /**
  90.          * A starter function for stubbing
  91.          * @param methodCallToStub call a method to stub as an argument
  92.          * @return an object providing stubbing options
  93.          */
  94.         public function given(methodCallToStub:*):Stubber
  95.         {
  96.             return mockito.given(methodCallToStub);
  97.         }
  98.  
  99.         /**
  100.          * @private
  101.          */
  102.         protected function get mockCreator():MockCreator
  103.         {
  104.             return mockito;
  105.         }
  106.  
  107.         /**
  108.          * Matches any argument including <code>null</code>
  109.          */
  110.         public function any():*
  111.         {
  112.             return mockito.any();
  113.         }
  114.  
  115.         /**
  116.          * Equality matcher
  117.          * Example:
  118.          * <listing>
  119.          * verify(never()).that(system.login(eq("root")));
  120.          * </listing>
  121.          */
  122.         public function eq(expected:*):*
  123.         {
  124.             return mockito.eq(expected);
  125.         }
  126.  
  127.         /**
  128.          * A fluent interface for making sure call hasn't happened
  129.          * Example:
  130.          * <listing>
  131.          * verify(never()).that(operator.execute());
  132.          * </listing>
  133.          */
  134.         public function never():Verifier
  135.         {
  136.             return mockito.never();
  137.         }
  138.  
  139.         /**
  140.          * A fluent interface for counting calls
  141.          * Example:
  142.          * <listing>
  143.          * verify(times(2)).that(operator.execute());
  144.          * </listing>
  145.          */
  146.         public function times(expectedCallsCount:int):Verifier
  147.         {
  148.             return mockito.times(expectedCallsCount);
  149.         }
  150.  
  151.         /**
  152.          * A fluent interface for custom matcher
  153.          * Example:
  154.          * <listing>
  155.          * verify().that(system.login(argThat(new HashOnlyCapitalLettersMatcher())));
  156.          * </listing>
  157.          *
  158.          * A good practice is to create a matcher recording function somewhere and name it
  159.          * after the matcher. It's important to return a wildcard from the function to let it
  160.          * work with any arugment of the function
  161.          * <listing>
  162.          * function hasOnlyCapitalLetters():*
  163.          * {
  164.          *     argThat(new HashOnlyCapitalLettersMatcher());
  165.          * }
  166.          * </listing>
  167.          */
  168.         public function argThat(matcher:Matcher):*
  169.         {
  170.             return mockito.argThat(matcher);
  171.         }
  172.     }
  173. }

I’ve built this against ASUnit3, and it appears to be running fine. As you can see, it’s release under the MIT license, as is Mockito-Flex. I’d appreciate any feedback that’s going, so have a play and let me know …

Rocks into Gold

Clarke Ching – whose work I’ve been reading for a while, is preparing to publish a short parable for these troubled times. Get in touch with him via this post, and grab a copy, after all the more weapons in our armoury, the better chance we have of winning the inevitable battles.

I want problems, not solutions!

So, there I was, quietly listening into a conference call between a couple of clients on one side, and the account manager, project manager and me on the other.

We were going through a small project that we’d just completed for the purposes of getting sign-off. We had built in the functionality they wanted, using the designs that they’d agreed to, so it was plain sailing.

And then the spanner.

Read more »

Finding out what’s best …

Just doing our best ain’t good enough – we need to be more savvy than that and work out precisely what’s the best thing to do first. So far, we’ve identified the conflict, and we now need to assess possible solutions.

Read more »

An evaporating conflict cloud

Doing our best doesn’t guarantee success, despite best intentions. How do we identify the behaviours that we want and don’t want, and find the inherent conflicts within the system?

Let’s take one of the problems in the previous article (It’s not rocket science), and see what’s driving it, which may give us a better perspective towards possible fixes.

Read more »

It’s not rocket science

How is it that people work hard for long hours, and yet projects fail? Why do project debriefs become bitter tales of one team thwarting another? How can we be doing our best, and yet see it fall apart so spectacularly?

Read more »

Will someone please charge for our creativity?

Why is it that digital creative agencies often only get paid for their implementation, and provide their creativity free? Unpaid-for work creates financial risk, resulting in rushed work when it’s most important.

Read more »

Software development processes

One of the most concise and accurate summaries of available processes that I’ve come across. If only more devs and Project Managers printed this out, we would have a much more successful industry record.

“Urgency is poisonous”

37 Signals are experimenting with a 4-day week, and finding it works.

They reckon that “urgency is acidic” – it burns out morale, especially when working towards an emergency deadline lasts more than a day or two (like, say 7 weeks plus – you know who you are!).

If your deliveries are that critical to the hour or day, maybe you’re setting up false priorities and dangerous expectations.

“Perishable Requirements”

Re-reading Agile Management for Software Engineering*, I got stuck on the phrase “perishable requirements”.

I re-read it several times, and each time it sunk in deeper just how important this concept is: this alone proves the worth of an agile approach to project development. Requirements go stale.

Most obviously, they run the risk of becoming obselete as the team and client’s understanding of the project evolves; but, equally importantly, they suffer atrophy simply through lack of use.

Once captured and defined, a requirement has a half-life – the longer it gets left in the requirements document without being actively worked on, the poorer the knowledge of that requirement. Clearly, if the developer leaves, the team suffers massive impact in its understanding of the requirement. But, even if the developer stays, their understanding and knowledge of the requirement withers as they work on other things.

The reality is that a requirement can rarely be so fully captured that it doesn’t depend on an individual’s understanding and definition of it.

The solution to this problem?

Define a sub-set of requirements that can be worked on within a specific timeframe. Move from requirements capture and definition to solution implementation within the same timeframe. Work agilely.

* Eli Schragenheim & David J. Anderson, Prentice Hall, 2003 (ISBN: 0-13-142460-2)