How to actually reset $httpBackend expectations?

2019-06-17 23:18发布

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?

3条回答
We Are One
2楼-- · 2019-06-17 23:37

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.

查看更多
戒情不戒烟
3楼-- · 2019-06-17 23:44

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
查看更多
一纸荒年 Trace。
4楼-- · 2019-06-17 23:44

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();
});
查看更多
登录 后发表回答