0

I have a javascript application where users can search for locations that are then displayed on a map. The search for locations is done with AJAX calls to a server application. There is one component responsible for this server communication (searchComponent) and I want to unit test if the communication works.

Description of the custom events

My custom events are a simple Publish/Subscribe implementation taken from http://api.jquery.com/jQuery.Callbacks/:

var topics = {};
jQuery.Topic = function( id ) {
    var callbacks,
    method,
    topic = id && topics[ id ];
    if ( !topic ) {
        callbacks = jQuery.Callbacks();
        topic = {
            publish: callbacks.fire,
            subscribe: callbacks.add,
            unsubscribe: callbacks.remove
        };
        if ( id ) {
            topics[ id ] = topic;
        }
    }
    return topic;
};

The most important methods are

  • EVENT.publish(data)
    Triggers an event and passes data to all subscribers.

  • EVENT.subscribe(callback) Subscribe the callback function to an EVENT: whenever the EVENT is triggered the callback function is executed.

Use case

The basic workflow is this:

  • user clicks search-button
  • the application calls searchComponent.doSearch()
  • searchComponent.doSearch() sends request to server
  • server responds
  • searchComponent triggers a custom event for either SEARCH_RESULT or SEARCH_FAILED
  • the application listens to both events and continues from there (show things on the map or produce an error message)

SEARCH_RESULT and SEARCH_FAILED are custom events as described above.

var SEARCH_RESULT = jQuery.Topic('SEARCH_RESULT');
var SEARCH_FAILED = jQuery.Topic('SEARCH_FAILED');

What do I want to do?

I want to test if the searchComponent is working:

  • Are requests to the server being made correctly?
  • Are the responses from the server handled correctly?
  • Does the search fail when I make an invalid call?
  • What about timeouts when the server is down?

The usual stuff. ;)

the question (finally ;))

How can I test this use case?
(preferrably using js-test-driver though I'm open for any suggestions on other javascript testing frameworks)

4

1 回答 1

0

It is possible to test asynchronous behaviour using [AsyncTestCase][1] in js-test-driver.

Here is an example test case for the doSearch() method. I've added comments to explain what each part of the test is doing.

MyTest = AsyncTestCase("MyTest", {

testSearchGoodCase : function(queue) {
    // this flag will only be set to true when SEARCH_RESULT 
    // is triggered (see STEP 1)
    var resultReceived = false;

    // STEP 1
    queue.call('prepare callbacks', function(callbacks) {

        // add event handler for the desired behaviour
        var onExpectedBehaviour = callbacks.add(function() {
            // when this method is called the queue will enter STEP 2
            resultReceived = true;
        });

        SEARCH_RESULT.subscribe(onExpectedBehaviour);

        // What if our test-method is not working and an error occurs?
        // Then the SEARCH_FAILED event is triggered, but for this
        // test case that is an error. So we can add the onError method 
        // as an errback in js-test-driver.

        // errbacks cause the test to fail with a custom message.
        var onError = callbacks.addErrback('Received an error.');

        // When SEARCH_FAILED is triggered onError is called
        // -> that will cause the test to fail
        // with the error message "Received an error".
        SEARCH_FAILED.subscribe(onError);

        // Now everything is set up and we can execute the function
        // that we want to test.
        searchComponent.doSearch();

        // The test will then run until either SEARCH_RESULT
        // or SEARCH_FAILED is triggered. Or the test will
        // timeout (if none of the two events is triggered).
    });

    // STEP 2
    queue.call('check conditions after asynchronous method completed', function() {

        // when we get here the doSearch() method completed
        // its asynchronous task.
        assertTrue(resultReceived);

    });        
}
}
于 2013-04-26T13:05:22.457 回答