Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple sequential httpBackend requests cause unexpected request

I'm testing a sequence that polls a resource until a condition is met.

Book = $resource("/books/:id", {id: "@id"});

function poll(success) {
  Book.get({id:1}, function() {
    if (canStop) {
       success();
    } else {
       $timeout(poll, 1000);
    }

  });
};

The test below fails with Error: Unsatisfied requests: GET /user_workshops/1

describe('poll', function() {
  beforeEach(function() {
    $httpBackend.expectGET('/books/1').respond(200,{id:1});
    $httpBackend.expectGET('/books/1').respond(200,{id:1, newVal:1});

    poll(function() {
       successCalled = true;
    });

    $httpBackend.flush();
    $timeout.flush();

    canStop=true;

    $httpBackend.flush();
  });

  it('should call success when canStop is true', function() {
     expect(successCalled).toBe(true);
  });
});

I've tried rearranging test order to put the second expectGET just before the second httpBackend.flush() but then I get:

Error: Unexpected request: POST /books/1
No more request expected
like image 322
ChrisJ Avatar asked Jul 28 '15 06:07

ChrisJ


1 Answers

After an hour of hair pulling I realised that the httpBackend is very specific about the order that tests a called in - the expectation must be set not just before you call flush, but before the resource request is made, and when you call flush you must have made exactly and only the requests expected.

This means if you want to flush between sequential requests, the order of requests and expectations must be exactly:

$httpBackend.expectGET('...')
resource.get();
$httpBackend.flush()
$httpBackend.expectGET('...')
resource.get();
$httpBackend.flush()
...
etc

So in the case of the code above, it works if I change the ordering to:

describe('poll', function() {
  beforeEach(function() {
    $httpBackend.expectGET('/books/1').respond(200,{id:1});

    poll(function() {
       successCalled = true;
    });

    $httpBackend.flush();

    $httpBackend.expectGET('/books/1').respond(200,{id:1, newVal:1});

    $timeout.flush();
    canStop=true;

    $httpBackend.flush();
  });

  it('should call success when canStop is true', function() {
     expect(successCalled).toBe(true);
  });
});
like image 148
ChrisJ Avatar answered Nov 08 '22 12:11

ChrisJ