4 Replies Latest reply on Jun 29, 2010 6:25 AM by luciano.bustos

    IExternalDependencyLoader throws a null pointer RTE

    luciano.bustos Level 1

      I'm trying to implement an async data loader as explained on the wiki. http://docs.flexunit.org/index.php?title=Using_External_Data_for_Parameterized_Testing_And _Theories#Custom_External_Dependency_Loader_example

       

      The test class is as follow.

       

      [RunWith("org.flexunit.runners.Parameterized")]
      public class TestExternalLoading {
      
           public static var dataRetriever:IExternalDependencyLoader = new ExternalDependencyLoader("books_catalog.xml");
       
           [Parameters(loader="dataRetriever")]
           public static var dataProvider:Object;
      
           [Test(dataProvider="dataProvider")]
           public function testDataLoaded():void {
                assertNotNull(dataProvider); //FAIL
           }
      }
      

       

      I've changed the ExternalDependencyLoader class in order to load an XML file via HTTP.  The file is loaded fine, but  myToken.notifyResult(event.result) ,inside ExternalDependencyLoader, method call fail.

       

      Anyone here can use this new API successfully?

        • 1. Re: IExternalDependencyLoader throws a null pointer RTE
          mlabriola Level 4

          the parameters metadata specifically means you are passing those params to the constructor. i also see you listing it as a dataprovider which makes me think that this is not what you wanted. can you confirm?

          • 2. Re: IExternalDependencyLoader throws a null pointer RTE
            luciano.bustos Level 1

            Yes, you're correct.

            I want that XML loaded into that variable. I toke that concept from http://www.flexunit.org/?p=72 . Loading external assets is a recurring use case.

            I thought that the the call "myToken.notifyResult(event.result)"  will handle the result an populate "dataProvider" variable on the TestClass.

             

            Is this approach possible??

            • 3. Re: IExternalDependencyLoader throws a null pointer RTE
              mlabriola Level 4

              Yes, it is possible. FlexUnit 4 supports two different types of Parameterized test.

               

              One uses [Parameters] metadata and requires that the arguments be passed to the constructor. The second types does not use the Parameters metadata and instead passed the data via the dataProvider argument of the [Test(dataProvider="")]

               

              Right now you are using part of each of those approaches.

               

              First, make sure you are using FlexUnit 4.1 beta 2 as we made this simpler in that version. Second, instead of implementing IExternalDataLoader implements IExternalDependencyData. It is the same interface with just one more property, a getter for the data.

               

              Then your syntax can be much simpler and look like this:

               

              public static var dataTwo:IExternalDependencyData = new ParamDataExt( "someFakeDataPath.stuff" );

               

              [Test(dataProvider="dataTwo")]
              public function timesTwoTest( value:int, result:int ):void {
                assertEquals( 2*value, result );
              }

               

              Notice that I don't have the [Parameters] metadata in this example, it is not needed. Here is the code for the ParamDataExt from this example:

               

              public class ParamDataExt implements IExternalDependencyData {

                private var dToken:ExternalDependencyToken;

                private var timer:Timer;

                private var _data:Array;

               

                public function get data():Array {

                  return _data;

                }

               

                private function success( data:TimerEvent ):void {

                  timer.removeEventListener(TimerEvent.TIMER_COMPLETE, success );

                  _data = [ [ 0, 0 ], [ 1, 2 ], [ 2, 4 ] ];

                  dToken.notifyResult( _data );

                }

               

               

                private function failure( info:* ):void {

                  _data = null;

                  dToken.notifyFault( "Totally broken" );

                }

               

               

              public function retrieveDependency( testClass:Class ):ExternalDependencyToken {

                  timer.start();

                  return dToken;

                }

               

               

                public function ParamDataExt( url:String ) {

                  timer = new Timer( 250, 1 );

                  timer .addEventListener(TimerEvent.TIMER_COMPLETE, success );

                  //Just fake this with a timer to illustrate the point

               

                  dToken = new ExternalDependencyToken();

                }

              Notice that the returned data is stored in a _data property and there is a getter for that data.
              Mike

              • 4. Re: IExternalDependencyLoader throws a null pointer RTE
                luciano.bustos Level 1

                Excelent! It worked.

                 

                Here is me DataLoader class.

                 

                public class XMLExternalDataLoader implements IExternalDependencyData {

                private var myToken:ExternalDependencyToken;

                private var my_loader:HTTPService;

                private var _data:Array;


                /**

                *

                * @param url the file you want to load

                * @param resultFormat the format used by the HTTPService

                *

                */

                public function XMLExternalDataLoader(url:String, resultFormat:String = "object") {

                myToken = new ExternalDependencyToken();

                my_loader = new HTTPService();

                my_loader.addEventListener(ResultEvent.RESULT, httpResultHandler);

                my_loader.addEventListener(FaultEvent.FAULT, httpFaultHandler);

                my_loader.resultFormat = resultFormat;

                my_loader.url = url;

                }


                /**

                * @inheritDoc

                */

                public function get data():Array {

                return _data;

                }


                /**

                * The fault handler

                * @param event

                *

                */

                protected function httpFaultHandler(event:FaultEvent):void {

                myToken.notifyFault(event.fault.toString());

                }


                protected function httpResultHandler(event:ResultEvent):void {

                _data = [[event.result]];

                myToken.notifyResult(_data);

                }


                public function retrieveDependency(testClass:Class):ExternalDependencyToken {

                my_loader.send();

                return myToken;

                }

                }

                 

                 

                And this is the implementation.

                 

                [RunWith("org.flexunit.runners.Parameterized")]
                public class ConfigTest {
                
                     public static var configLoader:IExternalDependencyData = new XMLExternalDataLoader("config.xml");
                
                     [Test(dataProvider="configLoader")]
                     public function testConfigNotNull(value:Object):void {
                          //value is the same as resultEvent.result.
                          assertNotNull(value);
                     }
                }

                 

                 

                And a final question:!

                 

                Is possible to return an object instead of an array of array containing the result.?

                This work "_data = [[event.result]];" but not in this way "_data = event.result".   //unable to convert.. Object to Array, etc.

                Thanks.!