首页 > 解决方案 > 如何在 jasmine 单元测试中触发 ngxsAfterBootstrap?

问题描述

在我的 Angular 应用程序中,我使用 NGXS 和 Jasmine。

在我的一些商店中,我使用 ngxsAfterBootstrap 作为初始化,在其中调度一些操作。

我不能使用 ngxsOnInit,因为不知道具体原因,但是我无法从我的 RouteState 选择器中获取最新的 url 参数(在 ngxsOnInit 中始终未定义,即使我订阅了这些选择器并等待了一些多少时间)

但是,使用 ngxsAfterBootstrap 我得到了这些值。

所以,在我的单元测试中,我想测试这个初始化,但我没有找到任何解决方案来触发 ngxsAfterBootstrap 方法。

根据 NGXS 文档(https://www.ngxs.io/advanced/life-cycle),ngxsAfterBootstrap 将通过 APP_BOOTSTRAP_LISTENER 触发,所以我认为这是我们使用 ngModule 的 'bootstrap' 属性时,它不存在于TestBed.configureTestingModule ...

我试图获取我的商店实例,手动调用他的 ngxsAfterBootstrap 方法,并将 StateContext 模拟为参数,但显然,因为 StateContext 是模拟的,所以当我使用他的调度时它不会触发我的动作......

你知道任何“干净”的解决方案吗?(这里的干净只是为了不修改我的实现以使单元测试正常工作)

谢谢 !(对不起,我的英语不好)

编辑:

我最终做了什么:

productStore = TestBed.inject(ProductState);

...

const stateContextMocked = {
      getState: jasmine.createSpy(),
      setState: jasmine.createSpy(),
      patchState: jasmine.createSpy(),
      dispatch: jasmine.createSpy(),
} as StateContext<IProduct>;

 ...

productStore.ngxsAfterBootstrap(stateContextMocked);

...

expect(stateContextMocked.dispatch).toHaveBeenCalledWith(new GetProductAction(productIdMocked));

我之前尝试过这样做,但我不喜欢它,因为我无法使用自动传入 ngxsAfterBootstrap 参数的“真实”StateContext 对象。

所以,我不能得到我的派遣结果。

但事实上,我可以只测试我的调度方法是否已被调用,并进行另一个测试来测试自己调度的动作。

这甚至是一个更好的方法^^

标签: angularjasminengxs

解决方案


假设我们要测试 ngOnInit。

  1. 在测试的 //Arrange 步骤中,我们模拟了所有外部依赖项,包括公共组件方法(顺便说一下,组件方法不是强制性的,这取决于我们的方法)。
  2. 然后在 //Act 中,我们通过简单地调用来触发 ngOnInit
component.ngOnInit();
  1. 最后在 //Assert 中,我们期望我们的间谍已经被调用。

同样的方法是 with ngxsAfterBootstrap,你应该把它看作一个简单的类方法。没有必要把事情复杂化。


推荐阅读