这是关于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;
});
});这是可行的。
然而,对于ngrx/store,它不是这样的(如果您用Store in代替TypeaheadService)。我认为您必须编写一个扩展Store的模拟类,然后将其提供给正在测试的组件,但我不确定为什么会这样(如果是这样的话)。
我只是困惑于如何在我的单元测试中模拟ngrx/store,并且在他们的网站或github上找不到任何文档。也许我疏忽了。
发布于 2016-11-30 19:23:24
感谢您发布这个问题并提出了一个潜在的解决方案!
我模拟它的方式是,在每次测试之前使用实际操作来设置初始状态,即模拟状态。下面是一个例子
beforeEach(inject([Store], (store: Store<ApplicationState>) => {
const someFakeState = {
counter: 9,
counterFilter: 'A_FAKE_COUNTER_FILTER'
};
store.dispatch(new myActionToSetSomeData(someFakeState));
}));在您的it()块中,您现在应该能够检查组件是否显示计数为9并按'A_FAKE_COUNTER_FILTER'进行过滤。
当然,您可以在it块中设置状态,而不是beforeEach,只要它在组件被实例化之前。
发布于 2017-09-20 23:52:15
您可以使用forRoot (>= v4)或provideStore ( <= v3)将数据提供给StoreModule,剩下的工作将为您完成:
1-导入:
import { StoreModule } from '@ngrx/store';2-创建模拟数据:
/*
* Mock data
*/
const PAINTS = [];3-在您的测试中导入:
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [ StoreModule.forRoot(PAINTS) ]
})
}))在以前的版本中(在v4之前),您应该使用provideStore(PAINTS)而不是forRoot(PAINTS)。请参阅changelog here
发布于 2016-11-29 13:35:17
是的,你必须模仿ngrx/store,但不仅仅是商店。Store需要三个参数;一个是Observable类型,另两个是Observable类型,这是一个接口。因此,我尝试了两种方法。将空值传递给StoreMock super()构造函数,但在我的断言中失败。我的另一个解决方案是使用模拟类(在本例中为Observable)实现观察者接口。这样,我就可以将定义的值传递给超级StoreMock构造函数。
这只是一个说明性的例子。ObservableMock实际上并不模拟我试图在应用程序中测试的任何功能。它起到了启动器的作用,这样Store就可以作为提供者注入到我正在测试的组件中。
由于观察者是一个接口,您必须在模拟中实现它的函数声明: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$);
}
}现在您可以将Store作为提供程序添加到组件的测试模块中。
describe('Component:Typeahead', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [...],
declarations: [Typeahead],
providers: [
{provide: Store, useClass: StoreMock} // NOTICE useClass instead of useValue
]
}).compileComponents();
});
});我相信还有其他方法可以做到这一点。因此,如果任何人有任何其他答案,请张贴他们!
https://stackoverflow.com/questions/40857864
复制相似问题