forked from ngrx/platform
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test(component): update usage of TestBed.get to TestBed.inject
angular 9 compatibillity changes for TestBed Closes ngrx#2240
- Loading branch information
1 parent
33241cb
commit 20132cc
Showing
52 changed files
with
31,495 additions
and
10,626 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,180 +1,181 @@ | ||
--- | ||
# The documentation below is for NgRx versions 6.x and older. | ||
# Visit https://ngrx.io for the latest documentation. | ||
--- | ||
|
||
# Testing | ||
|
||
## @ngrx/effects/testing | ||
|
||
### provideMockActions | ||
|
||
Provides a mock test provider of the `Actions` Observable for testing effects. This works well with writing | ||
marble tests and tests using the `subscribe` method on an Observable. The mock Actions will deliver a new Observable to subscribe to for each test. | ||
|
||
Details on marble tests and their syntax, as shown in the `hot` and `cold` methods, can be found in [Writing Marble Tests](https://github.com/ReactiveX/rxjs/blob/master/doc/writing-marble-tests.md). | ||
|
||
Usage: | ||
|
||
```ts | ||
import { TestBed } from '@angular/core/testing'; | ||
import { provideMockActions } from '@ngrx/effects/testing'; | ||
import { cold, hot } from 'jasmine-marbles'; | ||
import { Observable } from 'rxjs'; | ||
|
||
import { MyEffects } from './my-effects'; | ||
import * as MyActions from '../actions/my-actions'; | ||
|
||
describe('My Effects', () => { | ||
let effects: MyEffects; | ||
let actions: Observable<any>; | ||
|
||
beforeEach(() => { | ||
TestBed.configureTestingModule({ | ||
imports: [ | ||
// any modules needed | ||
], | ||
providers: [ | ||
MyEffects, | ||
provideMockActions(() => actions), | ||
// other providers | ||
], | ||
}); | ||
|
||
effects = TestBed.get(MyEffects); | ||
}); | ||
|
||
it('should work', () => { | ||
const action = new MyActions.ExampleAction(); | ||
const completion = new MyActions.ExampleActionSuccess(); | ||
|
||
// Refer to 'Writing Marble Tests' for details on '--a-' syntax | ||
actions = hot('--a-', { a: action }); | ||
const expected = cold('--b', { b: completion }); | ||
|
||
expect(effects.someSource$).toBeObservable(expected); | ||
}); | ||
}); | ||
``` | ||
|
||
It is also possible to use `ReplaySubject` as an alternative for marble tests: | ||
|
||
```ts | ||
import { TestBed } from '@angular/core/testing'; | ||
import { provideMockActions } from '@ngrx/effects/testing'; | ||
import { ReplaySubject } from 'rxjs'; | ||
|
||
import { MyEffects } from './my-effects'; | ||
import * as MyActions from '../actions/my-actions'; | ||
|
||
describe('My Effects', () => { | ||
let effects: MyEffects; | ||
let actions: ReplaySubject<any>; | ||
|
||
beforeEach(() => { | ||
TestBed.configureTestingModule({ | ||
imports: [ | ||
// any modules needed | ||
], | ||
providers: [ | ||
MyEffects, | ||
provideMockActions(() => actions), | ||
// other providers | ||
], | ||
}); | ||
|
||
effects = TestBed.get(MyEffects); | ||
}); | ||
|
||
it('should work', () => { | ||
actions = new ReplaySubject(1); | ||
actions.next(new MyActions.ExampleAction()); | ||
|
||
effects.someSource$.subscribe(result => { | ||
expect(result).toEqual(new MyActions.ExampleActionSuccess()); | ||
}); | ||
}); | ||
}); | ||
``` | ||
|
||
### getEffectsMetadata | ||
|
||
Returns decorator configuration for all effects in a class instance. | ||
Use this function to ensure that effects have been properly decorated. | ||
|
||
Usage: | ||
|
||
```ts | ||
import { TestBed } from '@angular/core/testing'; | ||
import { EffectsMetadata, getEffectsMetadata } from '@ngrx/effects'; | ||
import { MyEffects } from './my-effects'; | ||
|
||
describe('My Effects', () => { | ||
let effects: MyEffects; | ||
let metadata: EffectsMetadata<MyEffects>; | ||
|
||
beforeEach(() => { | ||
TestBed.configureTestingModule({ | ||
providers: [ | ||
MyEffects, | ||
// other providers | ||
], | ||
}); | ||
|
||
effects = TestBed.get(MyEffects); | ||
metadata = getEffectsMetadata(effects); | ||
}); | ||
|
||
it('should register someSource$ that dispatches an action', () => { | ||
expect(metadata.someSource$).toEqual({ dispatch: true }); | ||
}); | ||
|
||
it('should register someOtherSource$ that does not dispatch an action', () => { | ||
expect(metadata.someOtherSource$).toEqual({ dispatch: false }); | ||
}); | ||
|
||
it('should not register undecoratedSource$', () => { | ||
expect(metadata.undecoratedSource$).toBeUndefined(); | ||
}); | ||
}); | ||
``` | ||
|
||
### Effects as functions | ||
|
||
Effects can be defined as functions as well as variables. Defining an effect as a function allows you to define default values while having the option to override these variables during tests. This without breaking the functionality in the application. | ||
|
||
The following example effect debounces the user input into from a search action. | ||
|
||
```ts | ||
@Effect() | ||
search$ = this.actions$.pipe( | ||
ofType<Search>(BookActionTypes.Search), | ||
debounceTime(300, asyncScheduler), | ||
switchMap(...) | ||
``` | ||
The same effect but now defined as a function, would look as follows: | ||
```ts | ||
@Effect() | ||
// refactor as input properties and provide default values | ||
search$ = ({ | ||
debounce = 300, | ||
scheduler = asyncScheduler | ||
} = {}) => this.actions$.pipe( | ||
ofType<Search>(BookActionTypes.Search), | ||
debounceTime(debounce, scheduler), | ||
switchMap(...) | ||
``` | ||
Within our tests we can now override the default properties: | ||
```ts | ||
const actual = effects.search$({ | ||
debounce: 30, | ||
scheduler: getTestScheduler(), | ||
}); | ||
expect(actual).toBeObservable(expected); | ||
``` | ||
Doing this has the extra benefit of hiding implementation details, making your tests less prone to break due to implementation details changes. Meaning that if you would change the `debounceTime` inside the effect your tests wouldn't have to be changed,these tests would still pass. | ||
--- | ||
# The documentation below is for NgRx versions 6.x and older. | ||
# Visit https://ngrx.io for the latest documentation. | ||
--- | ||
|
||
# Testing | ||
|
||
## @ngrx/effects/testing | ||
|
||
### provideMockActions | ||
|
||
Provides a mock test provider of the `Actions` Observable for testing effects. This works well with writing | ||
marble tests and tests using the `subscribe` method on an Observable. The mock Actions will deliver a new Observable to subscribe to for each test. | ||
|
||
Details on marble tests and their syntax, as shown in the `hot` and `cold` methods, can be found in [Writing Marble Tests](https://github.com/ReactiveX/rxjs/blob/master/doc/writing-marble-tests.md). | ||
|
||
Usage: | ||
|
||
```ts | ||
import { TestBed } from '@angular/core/testing'; | ||
import { provideMockActions } from '@ngrx/effects/testing'; | ||
import { cold, hot } from 'jasmine-marbles'; | ||
import { Observable } from 'rxjs'; | ||
|
||
import { MyEffects } from './my-effects'; | ||
import * as MyActions from '../actions/my-actions'; | ||
|
||
describe('My Effects', () => { | ||
let effects: MyEffects; | ||
let actions: Observable<any>; | ||
|
||
beforeEach(() => { | ||
TestBed.configureTestingModule({ | ||
imports: [ | ||
// any modules needed | ||
], | ||
providers: [ | ||
MyEffects, | ||
provideMockActions(() => actions), | ||
// other providers | ||
], | ||
}); | ||
|
||
effects = TestBed.get(MyEffects); | ||
}); | ||
|
||
it('should work', () => { | ||
const action = new MyActions.ExampleAction(); | ||
const completion = new MyActions.ExampleActionSuccess(); | ||
|
||
// Refer to 'Writing Marble Tests' for details on '--a-' syntax | ||
actions = hot('--a-', { a: action }); | ||
const expected = cold('--b', { b: completion }); | ||
|
||
expect(effects.someSource$).toBeObservable(expected); | ||
}); | ||
}); | ||
``` | ||
|
||
It is also possible to use `ReplaySubject` as an alternative for marble tests: | ||
|
||
```ts | ||
import { TestBed } from '@angular/core/testing'; | ||
import { provideMockActions } from '@ngrx/effects/testing'; | ||
import { ReplaySubject } from 'rxjs'; | ||
|
||
import { MyEffects } from './my-effects'; | ||
import * as MyActions from '../actions/my-actions'; | ||
|
||
describe('My Effects', () => { | ||
let effects: MyEffects; | ||
let actions: ReplaySubject & lt; | ||
any & gt; | ||
|
||
beforeEach(() => { | ||
TestBed.configureTestingModule({ | ||
imports: [ | ||
// any modules needed | ||
], | ||
providers: [ | ||
MyEffects, | ||
provideMockActions(() => actions), | ||
// other providers | ||
], | ||
}); | ||
|
||
effects = TestBed.get(MyEffects); | ||
}); | ||
|
||
it('should work', () => { | ||
actions = new ReplaySubject(1); | ||
actions.next(new MyActions.ExampleAction()); | ||
|
||
effects.someSource$.subscribe(result => { | ||
expect(result).toEqual(new MyActions.ExampleActionSuccess()); | ||
}); | ||
}); | ||
}); | ||
``` | ||
|
||
### getEffectsMetadata | ||
|
||
Returns decorator configuration for all effects in a class instance. | ||
Use this function to ensure that effects have been properly decorated. | ||
|
||
Usage: | ||
|
||
```ts | ||
import { TestBed } from '@angular/core/testing'; | ||
import { EffectsMetadata, getEffectsMetadata } from '@ngrx/effects'; | ||
import { MyEffects } from './my-effects'; | ||
|
||
describe('My Effects', () => { | ||
let effects: MyEffects; | ||
let metadata: EffectsMetadata<MyEffects>; | ||
|
||
beforeEach(() => { | ||
TestBed.configureTestingModule({ | ||
providers: [ | ||
MyEffects, | ||
// other providers | ||
], | ||
}); | ||
|
||
effects = TestBed.get(MyEffects); | ||
metadata = getEffectsMetadata(effects); | ||
}); | ||
|
||
it('should register someSource$ that dispatches an action', () => { | ||
expect(metadata.someSource$).toEqual({ dispatch: true }); | ||
}); | ||
|
||
it('should register someOtherSource$ that does not dispatch an action', () => { | ||
expect(metadata.someOtherSource$).toEqual({ dispatch: false }); | ||
}); | ||
|
||
it('should not register undecoratedSource$', () => { | ||
expect(metadata.undecoratedSource$).toBeUndefined(); | ||
}); | ||
}); | ||
``` | ||
|
||
### Effects as functions | ||
|
||
Effects can be defined as functions as well as variables. Defining an effect as a function allows you to define default values while having the option to override these variables during tests. This without breaking the functionality in the application. | ||
|
||
The following example effect debounces the user input into from a search action. | ||
|
||
```ts | ||
@Effect() | ||
search$ = this.actions$.pipe( | ||
ofType<Search>(BookActionTypes.Search), | ||
debounceTime(300, asyncScheduler), | ||
switchMap(...) | ||
``` | ||
The same effect but now defined as a function, would look as follows: | ||
```ts | ||
@Effect() | ||
// refactor as input properties and provide default values | ||
search$ = ({ | ||
debounce = 300, | ||
scheduler = asyncScheduler | ||
} = {}) => this.actions$.pipe( | ||
ofType<Search>(BookActionTypes.Search), | ||
debounceTime(debounce, scheduler), | ||
switchMap(...) | ||
``` | ||
Within our tests we can now override the default properties: | ||
```ts | ||
const actual = effects.search$({ | ||
debounce: 30, | ||
scheduler: getTestScheduler(), | ||
}); | ||
expect(actual).toBeObservable(expected); | ||
``` | ||
Doing this has the extra benefit of hiding implementation details, making your tests less prone to break due to implementation details changes. Meaning that if you would change the `debounceTime` inside the effect your tests wouldn't have to be changed,these tests would still pass. |
Oops, something went wrong.