How to actually reset $httpBackend expectations?
Asked Answered
G

3

7

I've tried and tried to get this to work. The documentation is terse, at best:

resetExpectations(); - Resets all request expectations, but preserves all backend definitions. Typically, you would call resetExpectations during a multiple-phase test when you want to reuse the same instance of $httpBackend mock.

Every time my second request is called, my result always has the first result's data. Check out this fiddle http://jsfiddle.net/tbwn1gt0/2/ where I reset the expectations after the first flush, then set new expectations/result then flush again to yield the incorrect data.

// --- SPECS -------------------------
var url = '/path/to/resource';
var result = '';

describe('$httpBackend', function () {

    it("expects GET different results in subsequent requests", inject(function ($http, $httpBackend) {

        successCallback = function(data){
            result = data;            
        }
        // Create expectation
        $httpBackend.expectGET(url).respond(200, 'mock data');

        // Call http service
        $http.get(url).success(successCallback);

        // flush response
        $httpBackend.flush();
        console.log( result ); // logs 'mock data'

        // Verify expectations
        expect( result ).toContain('mock data'); // works as it should

        // reset the expectations
        $httpBackend.resetExpectations();

        // set the fake data AGAIN
        $httpBackend.expectGET(url).respond(200, 'doof the magic cragwagon');

        // get the service AGAIN
        $http.get(url).success(successCallback);
        expect( result ).toContain('doof'); // does not work, result is original result
        console.log( result ); // logs 'mock data'

    }));

});

// --- Runner -------------------------
(function () {
    var jasmineEnv = jasmine.getEnv();
    jasmineEnv.updateInterval = 1000;

    var htmlReporter = new jasmine.HtmlReporter();

    jasmineEnv.addReporter(htmlReporter);

    jasmineEnv.specFilter = function (spec) {
        return htmlReporter.specFilter(spec);
    };

    var currentWindowOnload = window.onload;

    window.onload = function () {
        if (currentWindowOnload) {
            currentWindowOnload();
        }
        execJasmine();
    };

    function execJasmine() {
        jasmineEnv.execute();
    }

})();

Other things I've tried include adding an afterEach with resetExpectations (putting each request in a new it statement). and a slew of other random attempts. If it try to change the expected url to something not expected, it errors as it should-- so I know the requests are getting handled through httpBackend at the very least.

Is this a defect or am I implementing it incorrectly?

Gettysburg answered 18/8, 2014 at 19:2 Comment(0)
N
4

The .resetExpectations() does work as you expected, but you just forgot to flush a http request for the second one.

// set the fake data AGAIN
$httpBackend.expectGET(url).respond(200, 'doof the magic cragwagon');

// get the service AGAIN
$http.get(url).success(successCallback);

$httpBackend.flush(); // flush the second http request here

expect( result ).toContain('doof'); // does not work, result is original result
console.log( result ); // logs 'mock data'

Example JSFiddle: http://jsfiddle.net/4aw0twjf/

PS. Actually, the $httpBackend.resetExpectations() is not necessary for your test case.

Nancinancie answered 18/8, 2014 at 19:13 Comment(3)
ah yes, so i can get the fiddle to work but not my actual production code. That, was simply a typo so that fiddle works. I guess my problem is with the promises in my service stack not firing properly.Gettysburg
Man, i must have something else going on-- I made a new fiddle jsfiddle.net/L4Lpn60g/3 with $q.defer resolve to mimic my production code case, but it works, unlike the production code =( the behavior I see, I can't reproduce in the fiddle. It seems like the promise code is getting called BEFORE the flush(). what the heck? it will take me a bit to make a fiddle that shows the same behavior, i'd reckon.Gettysburg
May be you could show your code around the $q.defer(). The fiddle would be great.Nancinancie
F
1

Your case doesn't require to reset expectations. You can modify behavior of expectation instead clear & create new one. "expectGET" (and other methods) returns requestHandler, e.g.:

// Create expectation
var expectationHandler = $httpBackend.expectGET(url).respond(200, 'mock data');

// Call http service, flush response, verify expectations

// Modify behavior
expectationHandler.respond(200, 'doof the magic cragwagon');

// Call http service ... AGAIN
Frankpledge answered 17/5, 2017 at 10:22 Comment(0)
U
0

Since you have multiple calls I would use this at the end of each test to verify that all http calls are successful expect($httpBackend.flush).not.toThrow();, which means that you don't have to invoke $httpBackend.flush(); for every http call.

Also, you it's nice to add an afterEach block like this.

afterEach(function () {
    $httpBackend.verifyNoOutstandingExpectations();
});
Upstart answered 16/12, 2015 at 12:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.