如何模拟@ ngrx/store?

Meg*_*gan 4 mocking jasmine rxjs ngrx

我想对一个组件进行单元测试.我正在使用@ ngrx/store和rxjs来从我的组件更新我的商店.为此,我订阅并取消订阅商店.我的单元测试失败了

TypeError:undefined不是config/spec-bundle.js中的对象(评估'this.store.unsubscribe')

我无法找到如何正确模拟我的商店及其事件发射器.

以下是以下几行:

app.component.ts:

  ngOnDestroy() {
    // unsubscribe the observable
    this.userStore.unsubscribe();
  }
Run Code Online (Sandbox Code Playgroud)

app.component.spec.ts:

我怎么嘲笑商店:

        export class MockStore extends Subject<fromRoot.State> implements Store <fromRoot.State> {}
Run Code Online (Sandbox Code Playgroud)

我如何配置:

        TestBed.configureTestingModule({
        imports: [
            FormsModule,
            ReactiveFormsModule,
            StoreModule.provideStore(reducer)
        ],
        declarations: [LoginComponent],
        providers: [
            BaseRequestOptions,
            MockBackend,
            { provide: AuthService, useValue: authServiceStub },
            { provide: LoginService, useValue: loginServiceStub },
            { provide: LoggerService, useValue: loggerServiceStub },
            {
                provide: Http, useFactory: (backend: ConnectionBackend,
                    defaultOptions: BaseRequestOptions) => {
                    return new Http(backend, defaultOptions);
                }, deps: [MockBackend, BaseRequestOptions]
            },
            { provide: Router, useClass: MockRouter }
        ]
  })
Run Code Online (Sandbox Code Playgroud)

告诉我你是否想要更多信息.提前致谢.

car*_*ant 8

您可以通过多种方式模拟商店,而您所做的将取决于您想要测试的方式.

当我在测试中模拟商店时,我只对两件事感兴趣:

  • 能够轻松地发出与测试相关的状态; 和
  • 能够看到在测试期间发送到商店的任何动作

我对在减速器上接线感兴趣,因为它们在其他地方进行了测试,所以这就是我所做的.

我使用这样的函数来创建一个Store来自两个Subject实例:

import { Action, Store } from "@ngrx/store";
import { Subject } from "rxjs/Subject";

export function mockStore<T>({
  actions = new Subject<Action>(),
  states = new Subject<T>()
}: {
  actions?: Subject<Action>,
  states?: Subject<T>
}): Store<T> {

  let result = states as any;
  result.dispatch = (action: Action) => actions.next(action);
  return result;
}
Run Code Online (Sandbox Code Playgroud)

在一个beforeEach我创建Store并添加到TestBed's providers:

actions = new Subject<Action>();
states = new Subject<AppState>();
store = mockStore<AppState>({ actions, states });

TestBed.configureTestingModule({
  imports: [EffectsTestingModule],
  providers: [
    {
      provide: Store,
      useValue: store
    },
    ...
  ]
});
Run Code Online (Sandbox Code Playgroud)

通过模拟Store注入组件 - 或效果,或者您正在测试的任何内容 - 然后在测试中发出特定状态 - 使用states主题 - 并且很容易检查以查看任何预期的操作已经被调度 - 通过订阅到这个actions主题.

关于你的错误,你不应该打电话unsubscribeStore; 您应该Subscription在订阅商店时返回的对象上调用它- 如另一个答案中所述.