views:

12

answers:

1

I'm just getting into QUnit testing, and have run into a problem on my first page :S

We use ASP.NET Service References to take advantage of async data loading on html pages, creating a reference to a web service in the same project. What ASP.NET does behind the scenes (ScriptManager control) is create a JS file representing the service methods and handling all the AJAX calling.

Using this, I have a page that calls one of these methods in the document.ready jQuery event. I'm now trying to test against this js file using QUnit, but avoid having the js file call the actual web service and use a mock service instead. Here's what I have for an attempt so far:

main.js (production code file)

var Service;

$(document).ready(function () {

    //class definition created by asp.net behind the scenes
    Service = MyProject.services.DataService;

    //the method that calls the service
    LoadData();
});

function LoadData() {
    Service.GetData(OnGetDataSuccess, OnGetDataFailure);
}

main-test.js (test QUnit code, main.js is referenced in this page)

function SetupMockService(result) {
    Service = { "GetData": function (OnSuccess, OnFailure) {
            GetDataCalled = true;
            OnSuccess(result);
            //this is required in an asyncTest callback, I think?
            start();
        }, "GetDataCalled": false};
}
$(document).ready(function () {
    module("LoadData");
    asyncTest("LoadData should call GetData from service", function () {
        SetupMockService(result);
        LoadData();
        equals(Service.GetDataCalled, true, "GetData has been called");
    });

This test fails. The LoadData method is called as part of the original (main.js) document.ready event, so it still calls the production web service, and the tests fail because that GetDataCalled variable is never set (or defined in production). Am I doing the asyncTest wrong? (This is my first day with QUnit, so I could very well be)

The other way I can see this working is if I can override the main.js document.ready event, but I'm not quite sure on how to do that. I also don't want to add "testEnvironment == true" checks to my production main.js code.

A: 

Turns out I had things a bit backwards, as well as one obvious mistake. Here's the resulting code that works

main-tests.js

//the test itself isn't calling async methods, so it doesn't need to use asyncTest
test("LoadData should call GetData from service", function () {
    SetupMockService();
    LoadData();
    equals(Service.GetDataCalled, true, "GetData has been called");
});

function SetupMockService() {
    //redefining the Service variable specified in main.js with a mock object
    Service = { "GetData": function (OnSuccess, OnFailure) {
            //I forgot the "this" part... d'oh!
            this.GetDataCalled = true;
        }, "GetDataCalled": false
    };
}

This still doesn't fix the issue with the original main.js's document.ready code being executed, but I'll figure that out.

RTigger