unit-testing - Angular 2 RC 如何对可观察的进行单元测试

标签 unit-testing angular karma-jasmine

我正在为 Angular 2 RC 应用程序编写一些测试,但在可观察量的测试方面遇到了一些问题。我模拟了将其类型设置为可观察的方法,但是当被测试的单元尝试订阅模拟的可观察时,我收到错误'无法读取未定义的属性'订阅'

我正在测试我的 DashboardComponent,它注入(inject) model3DService 并调用 model3DService.get3DModels() 这是一个执行 http 的可观察对象请求并返回 3D 模型对象的数组。

这是一些示例代码:

仪表板组件

import { Model3DService } from '../../services/model3D/model3D.service';
import { ProjectService } from '../../services/project/project.service';

@Component({
  selector: 'cmg-dashboard',
  styles: [require('./css/dashboard.scss')],
  template: require('./dashboard.html')
})
export class DashboardComponent implements OnInit {
  constructor(
    private projectService: ProjectService,
    private model3DService: Model3DService
  ) { }

  ngOnInit (): void {
    this.model3DService.get3DModels().subscribe((res: any[]) => {
      this.findProjects(res);
      this.models = res;
      this.projectService.isProjectSelected = true;
      this.createProject(res[0]);
    });
  }
}

Model3D服务

@Injectable()
export class Model3DService {
 private models: any[] = [];

 public get3DModels (): Observable<any> {
    return this.http.get('../../../json/3DModel.json')
    .map(( res: Response ) => {
      this.models = res.json();
      return this.models;
    });
  }
}

好吧,现在我们已经进行了测试,这就是我正在编写的测试。

仪表板组件规范

class MockModel3DService {
  public get3DModels(): Observable<any> {
    return;
  }
}

describe('Dashboard Component', () => {
  beforeEachProviders(() => {
    return [
      DashboardComponent,
      provide(ProjectService, {
        useClass: MockProjectService
      }),
      provide(Model3DService, {
        useClass: MockModel3DService
      })
    ];
  });

  describe('ngOnInit', () => {
    it('should call model3DService.get3DModels on init', (inject([DashboardComponent], (dashboardComponent: DashboardComponent, model3DService: MockModel3DService) => {
      dashboardComponent.ngOnInit();
      expect(model3DService.get3DModels).toHaveBeenCalled();
    })));
  });
});

最佳答案

这个概念类似于测试 AngularJS $q Promise。 stub 方法返回一个可观察的模拟。该方法可以返回一个主题,而不是 inherits Observable 但也具有 observables 和observers 的属性。

可以为新主题提供就地模拟值,需要事先定义模拟 promise (主题与延迟共享此属性,请参阅 the relevant question )。

RxJS 4 主题有 hasObservers 方法,可以避免 subscribe spy 。 RxJS 5 主题错过了该方法,但它们暴露了 observers 属性。

很可能应该是这样的

let subject: Subject;

class MockModel3DService {
  public get3DModels(): Observable<any> {
    return subject;
  }
}

...
// beforeEach(...)
subject = new Subject;
...

// it(...)
const models = ['mocked'];
dashboardComponent.ngOnInit();

expect(subject.observers.length).toBe(1);

subject.next(models);
expect(model3DService.get3DModels).toHaveBeenCalled();
expect(dashboardComponent.models).toBe(models);
...

关于unit-testing - Angular 2 RC 如何对可观察的进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38154584/

相关文章:

java - 使用包私有(private)方法以促进单元测试是一种好习惯吗?

c# - 无法在单元测试中从 FakeItEasy 模拟中触发事件

json - 如何断言两个 JSON 字符串表示的数据相等?

javascript - Jasmine 测试检查 html 是否包含文本并返回 bool 值

javascript - 使用不同的对象调用 Jasmine 测试

javascript - 为什么我的 Karma Jasmine 代码覆盖率总是 100%

unit-testing - 可重用的模拟与每个测试中的模拟

angular - MatAutocomplete 值 X 显示

javascript - Angular : Lazy load multiple Modules with the same route

javascript - 在 Angular Virtual Scroll 中使用父滚动条而不是子组件滚动条