4 Replies Latest reply on Feb 14, 2010 10:27 AM by jpsoul

    Mock-as3 problem

    RichOnYeti Level 1

      Hi,

       

      Anyone using Mock-as3?  I am and am having a problem.  In a nutshell I created an interface so I could mock the flash ExternalInterface class.  I'm setting expectations prior to calling methods that invoke a mock object built on this interface.  Here's the test code:

       

       

               appState.openWindows.push("window1");

               var args:Array = ["window2"];

             

               mockExternalInterface.mock.method('available').andReturn(true).anyNumberOfTimes;

               mockExternalInterface.mock.method('call').once.withArgs('closeWindow', args);

      //         mockExternalInterface.mock.method('closeWindow').withArgs('closeWindow', "window2").once;

               mockExternalInterface.mock.method('call').withArgs('closeMainWindow').once;

             

               var event:MenuEvent = new MenuEvent(MenuEvent.ITEM_CLICK);

               event.item = menu.menubarXML.menuitem.(@label == "LogoffAndExit");

               var myMainMenuEvent:MainMenuEvent = new MainMenuEvent(MainMenuEvent.CLICK);

               myMainMenuEvent.menuEvent = event;

             

               menu.menuHandler(myMainMenuEvent.menuEvent);

      The call to mockExternalInterface.available is working.  I get a "No Expectation set" error for "MockExternalInterface.call(closeWindow,window2) From Mock-as3.  I've tried setting the expectation using both the String "window2" and the Array "args".  Note the "call" method signature - I suspect that this might be the core of the problem.
      (Mock)ExternalInternalInterface.call(functionName:String, ...args);
      Thanks,
      Rich
        • 1. Re: Mock-as3 problem
          RichOnYeti Level 1

          ack!  Apologies for the code formatting :<

          • 2. Re: Mock-as3 problem
            RichOnYeti Level 1

            Trying the code snippet again...

             

            appState.openWindows.push("window1");

            var args:Array = ["window2"];

                  

            mockExternalInterface.mock.method('available').andReturn(true).anyNumberOfTimes ;

            mockExternalInterface.mock.method('call').once.withArgs('closeWindow', args);

            //mockExternalInterface.mock.method('closeWindow').

            //                      withArgs('closeWindow', "window2").once;

            mockExternalInterface.mock.method('call').withArgs('closeMainWindow').once;

                  

            var event:MenuEvent = new MenuEvent(MenuEvent.ITEM_CLICK);

            event.item = menu.menubarXML.menuitem.(@label == "LogoffAndExit");

            var myMainMenuEvent:MainMenuEvent = new MainMenuEvent(MainMenuEvent.CLICK);

            myMainMenuEvent.menuEvent = event;

                  

            menu.menuHandler(myMainMenuEvent.menuEvent);

            • 3. Re: Mock-as3 problem
              RichOnYeti Level 1

              I think I may have figured out the cause of the behavior I described below.  The  following article on the FUnit web site  describes a difference between JUnit and FlexUnit behavior WRT equality  comparisons on arrays.  Here's a short snippet from the  article:

               

              The  intent of ‘assertEquals’ according to xUnit convention is to ensure that the  value of two objects are identical, not that they reference the same object. A second assertion type  ‘assertSame’ exists in JUnit (’areSame’ for NUnit) to ensure that two objects  share the same memory  reference.

              This seems to explain what I was seeing so I did a quick test to see if this is what is going on in  mock-as3 as well  I changed my mock implementation to  store a reference to invocations of the ExternalInterface.call()  method:
              ...
              public var callInvocations:Array =  new Array();
              public function call(functionName:String, ...args):*
              {
                 callInvocations[callInvocationsCurrentIndex++] =  [functionName, args[0]];
                 return null;
              }
              ...
              I then checked the results, first  using:
              assertEquals(mockExternalInterface.callInvocations[0], ["closeWindow", "window2"]);
              This failed with a message basically stating that "<closeWindow,window2> doesn't equal  <closeWindow,window2>", the same message I got from  mock-as3.

              Then I changed the check to this:
              assertEquals(mockExternalInterface.callInvocations[0][0], "closeWindow");
              assertEquals(mockExternalInterface.callInvocations[0][1], "window2");
              Now the test passes.  Hmmm, seems like this might explain things.  If true, then mock-as3 will never work correctly for functions that contain a "...rest" argument.  Now if I can only figure out how to contact the mock-as3 guys and let them know what I think I've found.
              Hope this helps someone.
              Cheers,
              Rich
              • 4. Re: Mock-as3 problem
                jpsoul Level 1

                For reference, this would be n issue with Mock4AS as well. As a workaround, in Mock4AS I made the mock implementation look like this:

                 

                public function call(functionName:String, ..rest):void

                {

                     switch (rest.length):

                     {    

                          case 0:

                                record("functionName");

                                break;

                          case 1:

                               record("functionName", rest[0]);

                               break;

                          case 2:             

                               record("functionName", rest[0], rest[1]);

                          break;

                   // .. I usually go up to length of 5

                   // after that I should have probably sent an object

                     // instead of a huge parameter list

                     // then I throw an error if I try to send more so I know in my test what happened.

                          default:

                               throw new Error("Mock only supports up to 5 args");

                               break;


                          }    

                }

                 

                This is the idea, although I haven't compiled that word for word (it's not copied from my source code).

                 

                Another good feature to add to either Mock4AS or Mock-as would be hamcrest matchers. Then it could evaluate the contents of the array rather than just the reference.  I will be looking to add this feature to Mock4AS soon.