Jasmine is a simple, BDD-style JavaScript testing framework, but to benefit from the full power out of the framework, you need to know how to mock calls the Jasmine way.

Jasmine uses spies to mock asynchronous and synchronous function calls.  As with most mocking frameworks, you can set the externally observed behavior of the code you are mocking. 

Using Jasmine spies to mock code

Jasmine spies are easy to set up.  You set the object and function you want to spy on, and that code won't be executed. 

In the code below, we have a MyApp module with a flag property and a setFlag() function exposed.  We also have an instance of that module called myApp in the test.  To spy on the myApp.setFlag() function, we use:

spyOn(myApp, "setFlag");

It's a little strange that in Jasmine, you have to put the function you want to spy on in quotes, but that's the API.

When you spy on a function like this, the original code is not executed.

Returning values from Jasmine spies

Most of the time when setting up mocks, you want to set return values so you can test a specific code path.  Again, this is easy to do with Jasmine. 

Here, I show setting the return value of a function so we can test specific branches in the code and skip over the real getFlag() function, which is hard-coded to return false.

The key piece is intercepting the getFlag() function with the spy and setting the value the substituted function returns:

spyOn(myApp, "getFlag").and.returnValue(true);

Sometimes, setting a returnValue isn't enough.  If you need to replace the function you are mocking, you can use:

spyOn(myApp, "useFlagForSomething").and.callFake(function() {
    return "I'm replacing the real function with this";
});

Using Jasmine spies to verify code was called

You can also call the original code with a spy.  This may sound pointless (why set up a mock and then call the real code?) unless you think about interaction testing, where it's important to know that a function was or was not called.

The syntax to call the original code but still spy on the function is:

spyOn(myApp, "getFlag").and.callThrough();

The code below shows how you can verify a spied on function was called.  We have a new function called reallyImportantProcess().  We have to test to make sure it's being run under the right conditions, and we know it should run when getFlag() returns false, which is the default value.  So we don't need to mock or change getFalse() to take this code branch, but we do need to spyOn reallyImportantProcess() to verify it gets called. 

In this spy, we have lots of options.  We could skip calling the real code, as we do below, or we could set up specific return values or substitute our own function for that function, or we could call the original code with callThrough().  When you set up Jasmine spies, you can use any spy configuration and still see if it was called later with and toHaveBeenCalled().

You can also test that a spied on function was NOT called with:

expect(myApp.reallyImportantProcess).not.toHaveBeenCalled();

Or you can go further with your interaction testing to assert on the spied on function being called with specific arguments like:

expect(myApp.reallyImportantProcess).toHaveBeenCalledWith(123, "abc");

Using Jasmine to mock async calls

Async calls are a big part of JavaScript.  Most code dealing with async calls these day works through promises or callbacks. 

Here, some test helper code can be used to mock promises being returned from an async call.  I'm using jQuery's $.Deferred() object, but any promise framework should work the same.

You can mock an async success or failure, pass in anything you want the mocked async call to return, and test how your code handles it:

var JasmineHelpers = function () {

    var deferredSuccess = function (args) {
        var d = $.Deferred();
        d.resolve(args);
        return d.promise();
    };

    var deferredFailure = function (args) {
        var d = $.Deferred();
        d.reject(args);
        return d.promise();
    };

    return {
        deferredSuccess: deferredSuccess,
        deferredFailure: deferredFailure
    };
};

Here is some Jasmine spy code using these async helpers. Again, we use jQuery $.Deferred() object to set up a function that calls out to a pretend async call named testAsync().  It's invoked by callSomethingThatUsesAsync(), which is the function we're testing.  We want to mock the testAsync() call (maybe it goes off to the database and takes a while), and we want to assert that when that testAsync() call succeeds, callSomethingThatUsesAsync() goes on to give us a text message saying it succeeded.

Since the function under test is using a promise, we need to wait until the promise has completed before we can start asserting, but we want to assert whether it fails or succeeds, so we'll put our assert code in the always() function.  The done(), fail(), and always() functions are promise code - they are not specific to Jasmine.

This approach is one way to do this, but this blog post covers more techniques for testing async code with Jasmine.