0

我正在尝试使用规范文件编写测试,但出现以下错误:

TypeError: Cannot read property 'loading' of undefined- 无法理解要么解决它。

有人帮我吗?

这是我的 spec.ts 文件:

import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { provideMockStore, MockStore } from '@ngrx/store/testing';
import { ShellHomeComponent } from './shell-home.component';
import { StoreOne } from './../../models';
import { Store, select } from '@ngrx/store';
import { cold } from 'jasmine-marbles';
import { StoreModule } from '@ngrx/store';
import { reducer } from './../../state/reducer/reducer-storeOne';

describe('ShellHomeComponent', () => {

    let fixture: ComponentFixture<ShellHomeComponent>;
    let mockStore: MockStore<StoreOne>;
    let component: ShellHomeComponent;

    const loadingState = {
        loading: true,
        items: [{ name: '1' }]
    } as StoreOne;

    beforeEach(async(() => {
        TestBed.configureTestingModule({
            declarations: [ ShellHomeComponent ],
            providers: [provideMockStore({ initialState: loadingState })]
        })
        .compileComponents();

        mockStore = TestBed.get(Store);

    }));

    beforeEach(() => {
        fixture = TestBed.createComponent(ShellHomeComponent);
        component = fixture.componentInstance;
        fixture.detectChanges();
    });


    it('should display loading as true', () => {
        const expected = cold('a', { a: true });
        expect(component.loading).toBeObservable(expected);
    });

});

我得到的错误:

expect(received).toEqual(expected) // deep equality

    - Expected
    + Received

      Array [
        Object {
          "frame": 0,
          "notification": Notification {
    -       "error": undefined,
    -       "hasValue": true,
    -       "kind": "N",
    -       "value": true,
    +       "error": [TypeError: Cannot read property 'loading' of undefined],
    +       "hasValue": false,
    +       "kind": "E",
    +       "value": undefined,
          },
        },
      ]

      44 |     it('should display loading as true', () => {
      45 |         const expected = cold('a', { a: true });
    > 46 |         expect(component.loading).toBeObservable(expected);
         |                                   ^
      47 |     });
      48 |
      49 | });

      at compare (node_modules/jasmine-marbles/bundles/jasmine-marbles.umd.js:379:33)
      at src/app/module1/shell/shell-home/shell-home.component.spec.ts:46:35

  console.warn node_modules/@ngrx/store/bundles/store.umd.js:608
    The feature name "storeOne" does not exist in the state, therefore createFeatureSelector cannot access it.  Be sure it is imported in a loaded module using StoreModule.forRoot('storeOne', ...) or StoreModule.forFeature('storeOne', ...).  If the default state is intended to be undefined, as is the case with router state, this development-only warning message can be ignored.

我的 componet.ts 文件:

import { Component, OnInit, OnChanges } from '@angular/core';
import { StoreOne, Item } from './../../models';
import { Observable } from 'rxjs';
import { Store, select } from '@ngrx/store';
import * as slices from './../../state';
import * as actions from './../../state/actions';

@Component({
    selector: 'app-shell-home',
    templateUrl: './shell-home.component.html',
    styleUrls: ['./shell-home.component.scss']
})
export class ShellHomeComponent implements OnInit {

    constructor(private store: Store<StoreOne>) {}

    items: Observable<Item[]>;
    loading: Observable<boolean>;

    ngOnInit() {

        this.store.dispatch(actions.Items());
        this.items = this.store.pipe(select(slices.getItems));
        this.loading = this.store.pipe(select(slices.getLoad));

        this.store.subscribe(state => console.log(state));
       //{ "storeOne": { "loading": true, "items": [ {"name": "1" }, { "name": "2"} ] }}

    }


}

更新

我的加载状态更新为如下:

const loadingState = { storeOne: { loading: true, items: [{ name: 1 }] } } as StoreOne;

但得到一个错误:

TypeScript diagnostics (customize using `[jest-config].globals.ts-jest.diagnostics` option):
    src/app/module1/shell/shell-home/shell-home.component.spec.ts:16:26 - error TS2352: Conversion of type '{ storeOne: { loading: boolean; items: { name: number; }[]; }; }' to type 'StoreOne' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
      Type '{ storeOne: { loading: boolean; items: { name: number; }[]; }; }' is missing the following properties from type 'StoreOne': loading, items

    16     const loadingState = { storeOne: { loading: true, items: [{ name: 1 }] } } as StoreOne;
                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4

2 回答 2

3

就我而言,问题是进口的结构。我已经导入了一个模块

StoreModule.forFeature('name', nameReducer)

在一个模块内:

StoreModule.forFeature('name2', name2Reducer)

代码工作正常,但是当我测试它失败了。

解决方案是从模块的测试声明中导入模块的需要。

于 2019-12-26T17:34:51.800 回答
2

您的代码不必要地使用了单元测试和集成测试的技术。正确的解决方案取决于您的测试目标:

  • 如果您的目标是编写集成测试(使用它的实时依赖项测试您的组件),请导入forRoot
TestBed.configureTestingModule({
  declarations: [ ShellHomeComponent ],
  imports: [StoreModule.forRoot({ storeOne: reducer })]
  // no need to use mock store for an integration test, import your reducer using `forRoot`
})
  • 如果您的目标是编写一个单元测试(模拟商店),我相信它是,请提供MockStore
TestBed.configureTestingModule({
  declarations: [ ShellHomeComponent ],
  providers: [provideMockStore({ initialState: loadingState 
  // no need to import the `StoreModule` in a unit test, `provideMockStore` will do all the setup
})

在 AngularUP,我发表了关于单元测试与集成测试以及 MockStore 的演讲。

于 2019-10-02T15:54:06.707 回答