lundi 23 janvier 2017

Testing Asynchronous Code Using Backbone JS - Promises are resolving to incorrect objects

I have a Testing Suite for testing asynchronous code that's structure is as follows.

TestSuite = {
  "TestCollection": [],
  "GenerateTest": function( Input ) {
    return function() {
      return new rsvp.Promise(function( resolve ) {
        Input.Function( Input.Input ).then(function( Result ) {
          Input.ComparisonFunction( Result, Input.ExpectedOutput ).then(function( Passed ) {
            resolve( Passed );
          });
        });
      });
    };
  },
  "AddTest": function( Input ) {
    var xTest = this.GenerateTest( Input );
    this.TestCollection.push( xTest );
  },
  "TestAll": function() {
    return new rsvp.Promise(function( resolve ) {
      rsvp.All(
        _.map( this.TestCollection, function( Test ) {
          return Test();
        })
      ).then(function( PromiseResults ) {
        if (
          _.every( PromiseResults, function( PromiseResult ) {
            return PromiseResult.Value;
          })
        ) {
          log("All Tests Passed!");
          resolve( true ); 
        } else {
          log("Not all tests passed!");
          resolve( false );
        }
      });

    });
  }

}

The simple use case looks like:

//Method Under Test: 
function AsynchronousCode( Input ) {
  return new rsvp.Promise(function( resolve ) {
    wait( 5 ).then(function() {
      resolve( Input + 1 );
    });
  });
}

//Add test to test suite. 
TestSuite.add({
  "Input": 1,
  "Function": AsynchronousCode,
  "ExpectedOutput": 2,
  "ComparisonFunction": function( result, expected ) {
    return new rsvp.Promise(function( resolve ) {
      if ( result === expected ) {
        resolve( true );
      } else {
        resolve( false );
      }
    });
  }
});
xTestSuite.TestAll();
//Running the tests.


Actual use case that I need help with: I'm using backbone js to define a class model and a general method caller to call a method from that model.

//Actual Code.
//*
    var Model = backbone.Model.extend({
        "initialize": function() {},
        "defaults": {
            "Property": undefined,
            "Result": []
        },
        "method": function( Input ) {

            var xModel = this;
            var xState = this;

            return new rsvp.Promise(function( resolve ) {
                log("Start...");
                var Property = xModel.get("Property");
                var xResult = xModel.get("Result");
                xWait( Input ).then(function() {
                    xResult.push( Property + 1 );
                    log("Stop.");
                    resolve( xState );
                });
            });
        }
    });

    function GeneralMethodCaller( Input ) {
        return Input.Object.method( Input.Options );
    }

    var test = TestSuite.extend({
        "initialize": function() {
            log("test_simple initialized successfully!");
            var xTestSuite = this;
            xTestSuite.set("MethodUnderTest", "Simple");

            xTestSuite.add({
                "Async": true,
                "Name": "First Test",
                "Input": {
                    "Object": new Model({
                        "Property": 1,
                        "Result": []
                    }),
                    "Options": 5
                },
                "Function": function( Input ) {
                    log("First Test");
                    return new rsvp.Promise(function( resolve ) {
                        GeneralMethodCaller( Input ).then(function( State ) {
                            log( "State: " + JSON.stringify( State ));
                            resolve( State );   
                        });
                    });
                },
                "ExpectedOutput": [2],
                "Comparator": {
                    "Debug": true,
                    "Object": true
                }
            });

            xTestSuite.add({
                "Async": true,
                "Name": "Second Test",
                "Input": {
                    "Object": new Model({
                        "Property": 1,
                        "Result": []
                    }),
                    "Options": 5
                },
                "Function": function( Input ) {
                    log("Second Test");
                    return new rsvp.Promise(function( resolve ) {
                        GeneralMethodCaller( Input ).then(function( State ) {
                            log( "State: " + JSON.stringify( State ));
                            resolve( State );   
                        });
                    });
                },
                "ExpectedOutput": [3],
                "Comparator": {
                    "Debug": true,
                    "Object": true
                }
            });

            xTestSuite.test();

        }
    });

    var xTest = new test();


If I run my tests individually they run fine and all my tests pass but if I run them together, they're affecting eachothers state and if the promises don't return in the appropriate order then my tests fail. I'm instantiating a new model each time and I thought the promises resolved to each model respectively but that doesn't appear to be the case. Is there some kind of scoping technique or something I can do to correct this so that the promises resolve to the right object and stop affecting the others state or just some information in general maybe that could help enlighten me to what is goingn on under the hood...

THANK YOU SOOOOOOOOO MUCH IN ADVANCE!! I really appreciate any input!

Aucun commentaire:

Enregistrer un commentaire