5 Replies Latest reply on Oct 25, 2010 6:54 AM by injpix

    Can a mock method use it’s argument in a callback function?

    injpix Level 3

      This question isn’t directly related to FlexUnit, but I assume someone can give me advice on this problem or an alternative.  The problem is that I am trying to pass an instance of an object (AIRLoaderRequest) to a mocked object and need this mock object to invoke a method with the AIRLoaderRequest instance to the class (QueueManager) I am testing.

       

      Hopefully the code below will highlight my attempt using Mockolate.

      var request_a:AIRLoaderRequest = new AIRLoaderRequest("dummy_uri_a");
                     
      var loader:AIRLoader = nice(AIRLoader);
      mock(loader).method("sendRequest").args( instanceOf(AIRLoaderRequest) )
           .calls(function(request:AIRLoaderRequest):void 
           {
                queuemanager.sendNextRequest(request);
           });
      queuemanager.airloader = loader;
      
      queuemanager.queueRequest(request_a);//this will call loader.sendRequest()
      


       

       

       

      The request parameter above is never defined.  I understand that calls() takes a second parameter of an array that will be passed to the anonymous function, but I need something that will return the argument that queuemanager passed to it.

       

      There is a 2-way composition relationship between QueueManager and AIRLoader, so they’re tightly coupled to each other.  At any rate, to clarify, I need a test double to use its argument to invoke a method of the class being tested.

       

      Thanks.  If you need me to explain in more detail let me know, as l am sill learning the basics of unit testing and mocking.

        • 1. Re: Can a mock method use it’s argument in a callback function?
          drewbourne

          myIP, there is at least two ways to do what you want at the moment.

           

          The first is to use a CallsWithInvocation Answer which will call the given function with an Invocation object containing the name, arguments, and return value.

          
          var request_a:AIRLoaderRequest = new AIRLoaderRequest("dummy_uri_a");
                         
          var loader:AIRLoader = nice(AIRLoader);
          mock(loader).method("sendRequest").args( instanceOf(AIRLoaderRequest) )
              .answers(new CallsWithInvocationAnswer(function(invocation:Invocation):void {
                  var request:AIRLoaderRequest = invocation.arguments[0] as AIRLoaderRequest;
                  queuemanager.sendNextRequest(request);
              }));
          queuemanager.airloader = loader;
          
          queuemanager.queueRequest(request_a);//this will call loader.sendRequest()
          
          

           

          The second is to use argument capturing using a Capture instance and the capture argument matcher.

          
          var request_a:AIRLoaderRequest = new AIRLoaderRequest("dummy_uri_a");
               
          var captured:Capture = new Capture();
          var loader:AIRLoader = nice(AIRLoader);
          mock(loader).method("sendRequest").args(capture(captured))
              .calls(function():void {
                  var request:AIRLoaderRequest = captured.value as AIRLoaderRequest;
                  queuemanager.sendNextRequest(request);
              });
          queuemanager.airloader = loader;
          
          queuemanager.queueRequest(request_a);//this will call loader.sendRequest()
          

           

          I'll add .callsWithInvocation(fn:Function) and .callsWithArguments(fn:Function) shortcuts to help with this scenario.

          • 2. Re: Can a mock method use it’s argument in a callback function?
            injpix Level 3

            Drew, thanks for the reply.  Those solutions look awesome!  I'm eager to try them on Monday at work.

             

            And thanks for providing Mockolate, I am sure it will help me tremendously with my unit tests.

            • 3. Re: Can a mock method use it’s argument in a callback function?
              drewbourne Level 1

              myIP, I've added shortcuts to call a function with the Invocation or arguments to the latest code for Mockolate.

               

              
              mock(instance).method("example").anyArgs().callsWithInvocation(function(invocation:Invocation):void {
                  // use Invocation 
              });
              
              mock(instance).method("example").anyArgs().callsWithArguments(function(...args):void {
                  // use arguments
              });
              

               

               

               

              HTH

              1 person found this helpful
              • 4. Re: Can a mock method use it’s argument in a callback function?
                injpix Level 3

                That looks real nice, can't wait to try it!  Thanks.  I just might get a speeding ticket on my way to work tomorrow

                • 5. Re: Can a mock method use it’s argument in a callback function?
                  injpix Level 3

                  I just pulled, build and did a clean(which I had to remove and add the SWC back) in FB.  It works great, thanks again!