无法在角度测试用例中使用 TestBed.overrideProvider 覆盖 MAT_DIALOG_DATA 提供程序

Muh*_*man 5 testbed karma-jasmine angular-material angular

我正在尝试使用 TestBed 为 Angular 组件编写集成测试。有一些数据被注入到材质对话框的组件中,使用@inject(MAT_DIALOG_DATA). 我想测试两个案例。一种是没有提供数据时,另一种是提供一些数据时。但我想为所有情况(在beforeEach方法中)以相同的方式配置测试模块。因此,对于没有注入数据的情况,我将模块配置如下:

    TestBed.configureTestingModule({
          declarations: [
            PostNewComponent
          ].concat(EntryComponents1),
          imports: [TestingModule],
          providers: [
            PostService,
            { provide: MAT_DIALOG_DATA, useValue: {} },
            { provide: MatDialogRef, useValue: { close: (dialogResult: any) => {}, updateSize: () => {} }}
          ]
        });

Run Code Online (Sandbox Code Playgroud)

然后我有一个案例,我想测试通过的测试数据。所以我尝试了以下方法来覆盖提供者。

    TestBed.overrideProvider(MAT_DIALOG_DATA, {useValue : {name: "passedName"}});
Run Code Online (Sandbox Code Playgroud)

但它不会覆盖提供者。我调试了这个问题,发现 overrideProvider 最终在 core.js 中调用以下方法

        /**
     * Read the `ngInjectableDef` for `type` in a way which is immune to accidentally reading inherited
     * value.
     *
     * @param type A type which may have its own (non-inherited) `ngInjectableDef`.
     */
    function getInjectableDef(type) {
        var def = type[NG_INJECTABLE_DEF];
        // The definition read above may come from a base class. `hasOwnProperty` is not sufficient to
        // distinguish this case, as in older browsers (e.g. IE10) static property inheritance is
        // implemented by copying the properties.
        //
        // Instead, the ngInjectableDef's token is compared to the type, and if they don't match then the
        // property was not defined directly on the type itself, and was likely inherited. The definition
        // is only returned if the type matches the def.token.
        return def && def.token === type ? def : null;
    }
Run Code Online (Sandbox Code Playgroud)

MAT_DIALOG_DATA在不包含属性的情况下传递给该函数的“类型”参数ngInjectableDef。我对角度没有深入的了解,所以有人可以解释为什么它不起作用以及这个只读属性“ ngInjectableDef”到底是什么?

sup*_*guy 2

我遇到了类似的问题。不知道为什么它不起作用,但我能够针对我的情况使用解决方法。因为在组件的构造函数中我们有

@Inject(MAT_DIALOG_DATA) public data: any,
Run Code Online (Sandbox Code Playgroud)

我们可以在单独的测试中访问该值并更改它们的值,例如:

component.data.name = "passedName";
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助。

  • 我不建议这样做。仅仅为了测试而将类成员设置为公共是不好的做法。 (2认同)