I followed this guide to create an ngrx effect (app.effects.spec.ts):
https://nrwl.io/nx/guide-setting-up-ngrx
When running the unit test, I get
Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
I went over to ngrx platform repo and found this https://github.com/ngrx/platform/issues/553. But it was closed...
Can't reproduce. Could you give us a repo or link.
@Yonet
I just created another project with nx. Things work fine out of the box.
Once I update the libraries, I see the issue. Here is the branch that has the issue:
https://github.com/dereklin/nx-demo/tree/feature/update-libraries
The master branch is fine.
Thanks for checking.
Also, I am using windows 10. I had to run
npm i --no-optional
to install the dependencies.
To run the tests, I did
ng test --app=app1
This problem is due to jasmine-core. I downgraded from 2.8.0 to 2.6.2. The problem went away.
Here is the working repo: https://github.com/dereklin/nx-demo/tree/feature/figure-out-async-timeout
I think there is an issue with the reallAll function. It seems like the promise return from it never resolves. I was told at the jasmine repo that async was introduced at version 2.7. I tested a simple async test and it went through ok.
This is the failing repo: https://github.com/dereklin/nx-demo/tree/feature/figuring-out-jasmine-async-2
Here is my spec:
import { TestBed } from '@angular/core/testing';
import { StoreModule } from '@ngrx/store';
import { Actions } from '@ngrx/effects';
import { provideMockActions } from '@ngrx/effects/testing';
import { DataPersistence } from '@nrwl/nx';
import { readAll, hot } from '@nrwl/nx/testing';
import { AppEffects } from './app.effects';
import { of } from 'rxjs/observable/of';
export const return1 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1);
}, 5000);
});
};
describe('AppEffects', () => {
let actions;
let effects: AppEffects;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [StoreModule.forRoot({})],
providers: [AppEffects, DataPersistence, provideMockActions(() => actions)]
});
effects = TestBed.get(AppEffects);
});
describe('someEffect', () => {
it("should support async execution of test preparation and expectations", async () => {
expect(await return1()).toEqual(1);
}, 10000);
it('should work', async () => {
actions = hot('-a-|', { a: { type: 'LOAD_DATA' } });
expect(await readAll(effects.loadData)).toEqual([{ type: 'DATA_LOADED', payload: {} }]);
}, 50000);
});
});
I'm using jest and had the same problem. I tried using rxjs-marbles and the problem was resolved:
describe('someEffect', () => {
it('should work', marbles(async m => {
actions = m.hot('-a-|', { a: { type: 'LOAD_DATA' } });
expect(await readAll(effects.loadData)).toEqual([
{ type: 'DATA_LOADED', payload: {} }
]);
});
});
@mike-packetwerk
Thanks for the tip. There is a little syntax error in the code posted. Here is my working test:
describe("someEffect", () => {
it("should work", marbles(async(m) => {
actions = hot('-a-|', { a: { type: 'LOAD_DATA' } });
expect(await readAll(effects.loadData)).toEqual([{ type: 'DATA_LOADED', payload: {} }]);
}));
});
I am new to marbles. And from their example at https://github.com/cartant/rxjs-marbles
The hot and cold is from the m param. I change the test to use m.hot and it still works:
describe("someEffect", () => {
it("should work with m.hot", marbles(async(m) => {
actions = m.hot('-a-|', { a: { type: 'LOAD_DATA' } });
expect(await readAll(effects.loadData)).toEqual([{ type: 'DATA_LOADED', payload: {} }]);
}));
});
Do we still need this?:
import { hot } from '@nrwl/nx/testing';
I changed the generated specs to use toBeObservable instead of readAll (see here https://github.com/nrwl/nx/pull/267).
Both hot and cold use the test scheduler. The test scheduler controls the time, so you need to manually call flush on it to advance the time.
As a result, async/await and the test scheduler don't work together that well (they happen to work in some basic scenarios but break apart when in non-trivial scenarios). So from now on, the tests should either use one or the other.
Most helpful comment
I changed the generated specs to use toBeObservable instead of readAll (see here https://github.com/nrwl/nx/pull/267).
Both hot and cold use the test scheduler. The test scheduler controls the time, so you need to manually call flush on it to advance the time.
As a result, async/await and the test scheduler don't work together that well (they happen to work in some basic scenarios but break apart when in non-trivial scenarios). So from now on, the tests should either use one or the other.