Bri*_*nRT 7 unit-testing jasmine ngrx angular
这与Angular 2官方发布有关.我知道单元测试在beta,RC和官方发布之间发生了巨大变化.
当它在构造函数中用作参数时,在单元测试中模拟@ ngrx/store的好方法是什么?它并不像模拟服务那么简单.
例如,如果我想模拟服务,那么我可以这样做:
let serviceStub = { }; // not a true mocked service, just a stub, right?
let de: DebugElement;
let el: HTMLElement;
let nativeEl: Element;
let comp: Typeahead;
let fixture: ComponentFixture<Typeahead>;
describe('Component:Typeahead', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [...],
declarations: [Typeahead],
providers: [
{provide: TypeaheadService, useValue: serviceStub} // provides the service that is being "mocked"
]
}).compileComponents();
fixture = TestBed.createComponent(Typeahead);
nativeEl = fixture.nativeElement;
comp = fixture.componentInstance;
de = fixture.debugElement;
});
});
Run Code Online (Sandbox Code Playgroud)
这很有效.
对于ngrx/store,但是,它并没有(如果你在TypeaheadService替代店).我想你必须编写一个扩展Store的模拟类,然后将其提供给正在测试的组件,但我不确定为什么会这样(如果是这种情况).
我只是在如何模拟ngrx/store我的单元测试而无法在他们的网站或github上找到任何文档.也许我忽略了它.
小智 8
感谢您发布问题并建议可能的解决方案!
我嘲笑它的方法是,在每次测试之前使用实际操作来设置初始状态,即模拟状态.这是一个例子
beforeEach(inject([Store], (store: Store<ApplicationState>) => {
const someFakeState = {
counter: 9,
counterFilter: 'A_FAKE_COUNTER_FILTER'
};
store.dispatch(new myActionToSetSomeData(someFakeState));
}));
Run Code Online (Sandbox Code Playgroud)
在您的it()块内,您现在应该能够检查组件是否显示计数为9和过滤'A_FAKE_COUNTER_FILTER'.
您当然可以在it块内设置状态,而不是beforeEach在组件实例化之前设置状态.
您可以使用forRoot(> = v4)或provideStore(<= v3)将数据提供给StoreModule,其余的工作将为您完成:
1-导入:
import { StoreModule } from '@ngrx/store';
Run Code Online (Sandbox Code Playgroud)
2-创建模拟数据:
/*
* Mock data
*/
const PAINTS = [];
Run Code Online (Sandbox Code Playgroud)
3-将其导入您的测试中:
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [ StoreModule.forRoot(PAINTS) ]
})
}))
Run Code Online (Sandbox Code Playgroud)
在以前的版本(v4之前的版本)中,您应使用provideStore(PAINTS)代替forRoot(PAINTS)。在这里查看更改日志
是的,你确实必须模拟ngrx/store,但不仅仅是 Store。Store 需要三个参数;一个是 Observable 类型,两个是 Observer 类型,它是一个接口。所以,我尝试了两件事。将 null 值传递给 StoreMocksuper()构造函数,但在我的断言中失败了。我的另一个解决方案是使用模拟类(在本例中为 Observable)实现 Observer 接口。这样我就可以将定义的值传递到超级 StoreMock 构造函数中。
这只是一个说明性示例。ObservableMock 实际上并没有模拟我试图在应用程序中测试的任何功能。它充当启用程序,以便 Store 可以作为提供程序注入到我正在尝试测试的组件中。
由于 Observer 是一个接口,因此您必须在模拟中实现其函数声明:next、error和complete。
class ObservableMock implements Observer<any> {
closed?: boolean = false; // inherited from Observer
nextVal: any = ''; // variable I made up
constructor() {}
next = (value: any): void => { this.nextVal = value; };
error = (err: any): void => { console.error(err); };
complete = (): void => { this.closed = true; }
}
let actionReducer$: ObservableMock = new ObservableMock();
let action$: ObservableMock = new ObservableMock();
let obs$: Observable<any> = new Observable<any>();
class StoreMock extends Store<any> {
constructor() {
super(action$, actionReducer$, obs$);
}
}
Run Code Online (Sandbox Code Playgroud)
现在您可以将 Store 添加为组件的测试模块中的提供者。
describe('Component:Typeahead', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [...],
declarations: [Typeahead],
providers: [
{provide: Store, useClass: StoreMock} // NOTICE useClass instead of useValue
]
}).compileComponents();
});
});
Run Code Online (Sandbox Code Playgroud)
我确信还有其他方法可以做到这一点。所以如果有人还有其他答案,请留言!