Reputation: 9229
I have the following angular (4) test which should be testing a service, however, it seems to be passing before the Observable returns and expect
get's hit.
it('should enter the assertion', inject(
[ MockBackend, CellService ],
( backend: MockBackend, s: CellService ) => {
const urls = [];
backend.connections.subscribe((connection: MockConnection) => {
const req = connection.request;
urls.push(req.url);
if (req.method === RequestMethod.Get && req.url === '/api/getTest') {
connection.mockRespond(new Response(new ResponseOptions('enter mocked content')));
}
});
s.getCell('powders').subscribe(val => expect(true).toBeFalsy())
})
);
I tried adding async/await, but that didn't make a difference. How can I do this?
Update:
This code passes too ...
it('should enter the assertion', async(inject(
[ MockBackend, CellService ],
( backend: MockBackend, s: CellService ) => {
const urls = [];
backend.connections.subscribe((connection: MockConnection) => {
const req = connection.request;
urls.push(req.url);
if (req.method === RequestMethod.Get && req.url === '/api/getTest') {
connection.mockRespond(new Response(new ResponseOptions('enter mocked content')));
}
});
s.getCell('powders').subscribe(val => expect(true).toBeFalsy())
})
));
Upvotes: 2
Views: 1731
Reputation: 2530
You can use waitForAsync
which is intended exactly for this and works both with observables and promises.
Wraps a test function in an asynchronous test zone. The test will automatically complete when all asynchronous calls within this zone are done. Can be used to wrap an inject call. (doc)
it('...', waitForAsync(inject([AClass], (object) => {
object.doSomething.subscribe(() => {
expect(...);
})
})));
Upvotes: 0
Reputation: 209012
Wrap the test in Angular's async
import { async } from '@angular/core/testing';
---==== vvvv ===----
it('should enter the assertion', async(inject(
[ MockBackend, CellService ],
( backend: MockBackend, s: CellService ) => {
...
})
));
This will wrap the test in a test zone, which will allow Angular to actually wait for all the asynchronous tasks to complete before finishing the test.
See also:
Try it with fakeAsycn
/tick
import { fakeAsync } from '@angular/core/testing';
it('should enter the assertion', fakeAsync(inject(
[ MockBackend, CellService ],
( backend: MockBackend, s: CellService ) => {
...
let value;
s.getCell('powders').subscribe(val => {
value = val;
})
tick();
expect(val).toBeTruthy();
})
));
It should work with async
, but using fakeAsync
makes it a little easier to debug, since every thing is synchronous.
If it still doesn't work, then you may need to check the logic somewhere else. One of the checks I would make is here
req.method === RequestMethod.Get && req.url === '/api/getTest'
Are you sure both of these pass? If not, there will be no response.
Upvotes: 2
Reputation: 2141
I would prefer to use Jasmine done()
callback here.
First, get rid off injectors in the spec and use TestBed.get(serviceToken)
in beforeEach
section.
Second, pass done as parameter of spec function
it('should use asynchronous', done => {
s.method().subscribe(result => {
expect(result).toBe(...);
done();
}
})
Upvotes: 0