如何测试使用Redux的Angular组件?

时间:2018-04-19 09:48:18

标签: angular unit-testing redux angular5

我已经开始使用使用Redux的Angular(5)SPA,我也想知道是否可以执行组件(单元)测试。

我将提供一个简单的功能 - 从服务器获取一些待办事项数据:

todo.service.ts

  getTodos(): Observable<any> {
    this.ngRedux.dispatch({ type: SHOW_LOADER, message: "Loading TODOs ..." });

    let obs = this.http.get<Array<any>>("api/SampleData/GetTodoList");
      obs.subscribe(result => {
        console.log("Got todos:", result);
        this.ngRedux.dispatch({ type: HIDE_LOADER });
        this.ngRedux.dispatch({ type: FETCH_TODOS_SUCCESS, todos: result });
      },
      error => {
        this.ngRedux.dispatch({ type: HIDE_LOADER, message: "" });
        console.error(error);
      });
    return obs;
  }

通常,不需要返回Observable对象,因为此函数负责在自己的订阅上分派消息。但是,为了测试组件,它必须得到这个参考。

待办事项-list.component.ts

  constructor(
    private ngRedux: NgRedux<IAppState>,
    private todoService: TodoService) {
  }

  resetTodoList() {
    this.todoService.getTodos();
  }

因此,为了测试TodoListComponent.resetTodoList,我必须模拟TodoListComponent个依赖项,或者至少确保在执行测试时不调用它们:

待办事项-list.component.spec.ts

describe('TodosComponent', () => {
  let component: TodoListComponent;
  let service: TodoService;

  beforeEach(() => {
    service = new TodoService(null, null);

    component = new TodoListComponent(null, service);
  });

  it('should set todos property with server items', () => {
    spyOn(service, "getTodos").and.callFake(() => {
      return Observable.of([1, 2, 3]);
    });

  // act and assert should come here
  });
});

由于resetTodoList没有返回任何内容,我想让它返回Observable并在我的测试中订阅它:

  resetTodoList() {
    return this.todoService.getTodos();
  }

  // act and assert part from the test
  component.resetTodoList().subscribe(v => {
      expect(v.length).toBe(3);
  });

这种模式看起来很简单,但这意味着开发人员必须注意返回一个Observable引用,以使该函数可测试。

我想知道这种方法是否有其他选择。

问题:如何测试使用Redux的Angular组件?

P.S。我将在此处添加package.json相关内容,以提供更好的背景信息:

  "dependencies": {
    "@angular-redux/store": "^7.1.1",
    "@angular/animations": "^5.2.0",
    "@angular/cdk": "^5.2.4",
    "@angular/common": "^5.2.0",
    "@angular/compiler": "^5.2.0",
    "@angular/core": "^5.2.0",
    "@angular/forms": "^5.2.0",
    "@angular/http": "^5.2.0",
    "@angular/material": "^5.2.4",
    "@angular/platform-browser": "^5.2.0",
    "@angular/platform-browser-dynamic": "^5.2.0",
    "@angular/router": "^5.2.0",
    "angular-font-awesome": "^3.1.2",
    "bootstrap": "^4.1.0",
    "core-js": "^2.4.1",
    "font-awesome": "^4.7.0",
    "hammerjs": "^2.0.8",
    "jquery": "^3.3.1",
    "material-design-icons": "^3.0.1",
    "ng-block-ui": "^1.0.4",
    "ng2-select": "^2.0.0",
    "ng2-table": "^1.3.2",
    "ngx-bootstrap": "^2.0.3",
    "popper.js": "^1.14.3",
    "redux": "^3.7.2",
    "rxjs": "^5.5.6",
    "tassign": "^1.0.0",
    "zone.js": "^0.8.19"
  },
  "devDependencies": {
    "@angular/cli": "~1.7.4",
    "@angular/compiler-cli": "^5.2.0",
    "@angular/language-service": "^5.2.0",
    "@types/jasmine": "~2.8.3",
    "@types/jasminewd2": "~2.0.2",
    "@types/node": "~6.0.60",
    "codelyzer": "^4.0.1",
    "jasmine-core": "~2.8.0",
    "jasmine-spec-reporter": "~4.2.1",
    "karma": "~2.0.0",
    "karma-chrome-launcher": "~2.2.0",
    "karma-coverage-istanbul-reporter": "^1.2.1",
    "karma-jasmine": "~1.1.0",
    "karma-jasmine-html-reporter": "^0.2.2",
    "protractor": "~5.1.2",
    "ts-node": "~4.1.0",
    "tslint": "~5.9.1",
    "typescript": "~2.5.3"
  }

0 个答案:

没有答案