Skip to content

Commit

Permalink
fix(store): remove afterEach hook in mock store (#3245)
Browse files Browse the repository at this point in the history
Closes #3243
  • Loading branch information
cedricduffournet authored Dec 7, 2021
1 parent d24dde1 commit 0640085
Show file tree
Hide file tree
Showing 11 changed files with 58 additions and 126 deletions.
103 changes: 0 additions & 103 deletions modules/store/testing/spec/mock_store.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -516,106 +516,3 @@ describe('Refreshing state', () => {
expect(getTodoItems('li')[0].nativeElement.textContent.trim()).toBe('bbb');
});
});

describe('Cleans up after each test', () => {
const selectData = createSelector(
(state: any) => state,
(state) => state.value
);

it('should return the mocked selectors value', (done: any) => {
TestBed.configureTestingModule({
providers: [
provideMockStore({
initialState: {
value: 100,
},
selectors: [{ selector: selectData, value: 200 }],
}),
],
});

const store = TestBed.inject(Store);
store.pipe(select(selectData)).subscribe((v) => {
expect(v).toBe(200);
done();
});
});

it('should return the real value', (done: any) => {
TestBed.configureTestingModule({
imports: [
StoreModule.forRoot({} as any, {
initialState: {
value: 300,
},
}),
],
});

const store = TestBed.inject(Store);
store.pipe(select(selectData)).subscribe((v) => {
expect(v).toBe(300);
done();
});
});
});

describe('Resets selectors after each test', () => {
const selectorUnderTest = createSelector(
(state: any) => state,
(state) => state.value
);
let shouldSetMockStore = true;

function setupModules(isMock: boolean) {
if (isMock) {
TestBed.configureTestingModule({
providers: [
provideMockStore({
initialState: {
value: 100,
},
selectors: [{ selector: selectorUnderTest, value: 200 }],
}),
],
});
} else {
TestBed.configureTestingModule({
imports: [
StoreModule.forRoot({} as any, {
initialState: {
value: 300,
},
}),
],
});
}
}

/**
* Tests run in random order, so that's why we have two attempts (one runs
* before another - in any order) and whichever runs the test first would
* setup MockStore and override selector. The next one would use the regular
* Store and verifies that the selector is cleared/reset.
*/
it('should reset selector - attempt one', (done: any) => {
setupModules(shouldSetMockStore);
const store: Store<{}> = TestBed.inject(Store);
store.select(selectorUnderTest).subscribe((v) => {
expect(v).toBe(shouldSetMockStore ? 200 : 300);
shouldSetMockStore = false;
done();
});
});

it('should reset selector - attempt two', (done: any) => {
setupModules(shouldSetMockStore);
const store: Store<{}> = TestBed.inject(Store);
store.select(selectorUnderTest).subscribe((v) => {
expect(v).toBe(shouldSetMockStore ? 200 : 300);
shouldSetMockStore = false;
done();
});
});
});
13 changes: 0 additions & 13 deletions modules/store/testing/src/mock_store.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Inject, Injectable } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { Observable, BehaviorSubject } from 'rxjs';
import {
Action,
Expand All @@ -15,18 +14,6 @@ import { MockState } from './mock_state';
import { MockSelector } from './mock_selector';
import { MOCK_SELECTORS } from './tokens';

if (typeof afterEach === 'function') {
afterEach(() => {
try {
const mockStore: MockStore | undefined = TestBed.inject(MockStore);
if (mockStore) {
mockStore.resetSelectors();
}
// eslint-disable-next-line no-empty
} catch {}
});
}

type OnlyMemoized<T, Result> = T extends string | MemoizedSelector<any, any>
? MemoizedSelector<any, Result>
: T extends MemoizedSelectorWithProps<any, any, any>
Expand Down
1 change: 1 addition & 0 deletions projects/example-app/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ module.exports = {
moduleNameMapper: {
tslib: '<rootDir>../../node_modules/tslib/tslib.es6.js',
},
testRunner: 'jest-circus/runner',
};
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ describe('Login Page', () => {
};
instance.form.setValue(credentials);

spyOn(instance.submitted, 'emit');
jest.spyOn(instance.submitted, 'emit');
instance.submit();

expect(instance.submitted.emit).toHaveBeenCalledWith(credentials);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ describe('Login Page', () => {
instance = fixture.componentInstance;
store = TestBed.inject(MockStore);

spyOn(store, 'dispatch');
jest.spyOn(store, 'dispatch');
});

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ describe('AuthEffects', () => {
routerService = TestBed.inject(Router);
dialog = TestBed.inject(MatDialog);

spyOn(routerService, 'navigate').and.callThrough();
jest.spyOn(routerService, 'navigate');
});

describe('login$', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ describe('Collection Page', () => {
instance = fixture.componentInstance;
store = TestBed.inject(MockStore);

spyOn(store, 'dispatch');
jest.spyOn(store, 'dispatch');
});

it('should compile', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ describe('Find Book Page', () => {
instance = fixture.componentInstance;
store = TestBed.inject(MockStore);

spyOn(store, 'dispatch');
jest.spyOn(store, 'dispatch');
});

it('should compile', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ describe('Selected Book Page', () => {
instance = fixture.componentInstance;
store = TestBed.inject(MockStore);

spyOn(store, 'dispatch');
jest.spyOn(store, 'dispatch');
});

it('should compile', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { MemoizedSelector } from '@ngrx/store';
import { Store, StoreModule } from '@ngrx/store';
import { provideMockStore, MockStore } from '@ngrx/store/testing';
import { TestBed, ComponentFixture } from '@angular/core/testing';
import { HttpClientTestingModule } from '@angular/common/http/testing';
Expand Down Expand Up @@ -96,3 +97,51 @@ describe('AppComponent', () => {
//#enddocregion mockSelector
});
});

//#docregion resetMockSelector
describe('AppComponent reset selectors', () => {
let store: MockStore;

afterEach(() => {
store?.resetSelectors();
});

it('should return the mocked value', (done: any) => {
TestBed.configureTestingModule({
providers: [
provideMockStore({
selectors: [
{
selector: selectBooks,
value: [
{
id: 'mockedId',
volumeInfo: {
title: 'Mocked Title',
authors: ['Mocked Author'],
},
},
],
},
],
}),
],
});

store = TestBed.inject(MockStore);

store.select(selectBooks).subscribe((mockBooks) => {
expect(mockBooks).toEqual([
{
id: 'mockedId',
volumeInfo: {
title: 'Mocked Title',
authors: ['Mocked Author'],
},
},
]);
done();
});
});
});
//#enddocregion resetMockSelector
6 changes: 2 additions & 4 deletions projects/ngrx.io/content/guide/store/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,9 @@ Usage:

In this example based on the [walkthrough](guide/store/walkthrough), we mock the `selectBooks` selector by using `overrideSelector`, passing in the `selectBooks` selector with a default mocked return value of an array of books. Similarly, we mock the `selectBookCollection` selector and pass the selector together with another array. In the test, we use `setResult()` to update the mock selectors to return new array values, then we use `MockStore.refreshState()` to trigger an emission from the `selectBooks` and `selectBookCollection` selectors.

<div class="alert is-helpful">

**Note:** `MockStore` will reset all of the mocked selectors after each test (in the `afterEach()` hook) by calling the `MockStore.resetSelectors()` method.
You can reset selectors by calling the `MockStore.resetSelectors()` method in the `afterEach()` hook.

</div>
<code-example header="src/app/app.component.spec.ts (Reset Mock Selector) " path="store-walkthrough/src/app/tests/app.component.1.spec.ts" region="resetMockSelector"></code-example>

Try the <live-example name="testing-store"></live-example>.

Expand Down

0 comments on commit 0640085

Please sign in to comment.