【问题标题】:Angular 2 TestBed with mocks带有模拟的Angular 2 TestBed
【发布时间】:2016-12-19 06:15:39
【问题描述】:

我正在尝试测试使用其他服务的组件。我想通过为服务提供模拟来隔离组件。在 RC5 之前,我可以简单地使用 addproviders,它现在已被弃用,将被下一个 RC 删除。相反,我必须使用TestBed。当我出于某种原因提供模拟角度时,请继续寻找模拟所依赖的服务。并抛出DI exception。当我提供所有依赖项时,测试工作,但我不想为每个测试套件重复自己。这打破了基本的面向对象原则。 我的测试套件:

describe('Component: DummyRestApi', () => {

  class DummyRestApiTestService {

    GetAll() {

      return Rx.Observable.create(observer => {

        let data:Data[] = [];

        data.push({
          id: 0,
          data: 'data'
        });

        observer.next(data);
        observer.complete();

      });
    }

    Add(data) {
    }
  }
  let fixture;
  let myMockWindow:Window;
  // ToDo use the mocks
  beforeEach(() => {
    myMockWindow = <any> {location: <any> {hostname: '127.0.0.1'}};
    TestBed.configureTestingModule({
      declarations: [DummyRestApiComponent],
      providers: [
        // ServerAddressResolverService,
        DummyRestApiComponent,
        // ConfigurationService,
        {provide: DummyRestApiService, useClass: DummyRestApiTestService},
        // {provide: Window, useValue: myMockWindow}
      ],
      imports: [FormsModule, HttpModule]
    });
    TestBed.compileComponents().catch(error => console.error(error));


    // addProviders([
    //   DummyRestApiComponent,
    //   {provide: DummyRestApiService, useClass: DummyRestApiTestService},
    // ]);
  });


  describe('Initializing', () => {

    beforeEach(async(() => {
      console.log('Compiling');
      TestBed.compileComponents().catch(error => console.error(error));
      console.log('Compiling again');
    }));

    it('should create an instance', async(() => {
        var fixture = TestBed.createComponent(DummyRestApiComponent);
        fixture.detectChanges();
        expect(fixture.debugElement.componentInstance).toBeTruthy();
      }
    ));

});

Angular 2.0.0-RC5

【问题讨论】:

  • 我确认了这一点。您必须指定服务的导入,就好像它没有被模拟一样。至少在 RC5 中。不过,测试将使用模拟服务。

标签: unit-testing angular mocking testbed angular2-providers


【解决方案1】:

请注意,Patrick Ineichens 的回答使用的是提供,已弃用。

 providers: [provide(TodoService, { useValue: this.service })]

应该改为:

 providers: [{provide:TodoService, useValue: this.service }]

【讨论】:

    【解决方案2】:

    我刚刚将我的种子项目更新为 RC5,我的一个简单 todo 组件的测试套件如下所示:

    import { provide } from '@angular/core';
    import { TestBed, ComponentFixture, async } from '@angular/core/testing';
    import { Observable } from 'rxjs/Observable';
    import 'rxjs/add/observable/of';
    
    import { TodoModule } from './todo.module';
    import { TodoComponent } from './todo.component';
    import { Todo, TodoService } from './todo.service';
    
    class MockTodoService {
        get todos$(): Observable<Todo[]> {
            return Observable.of<Todo[]>([
                { task: 'Task 1', description: 'Description 1', completed: false },
                { task: 'Task 2', description: 'Description 2', completed: false }
            ]);
        }
    
        loadAll() { }
    
        add(newTodo: Todo) { }
    }
    
    describe('TodoComponent', () => {
    
        beforeEach(() => {
            this.service = new MockTodoService();
    
            TestBed.configureTestingModule({
                imports: [TodoModule],
                providers: [provide(TodoService, { useValue: this.service })]
            });
    
            this.fixture = TestBed.createComponent(TodoComponent);
        });
    
        it('should print out todo tasks', async(() => {
            this.fixture.whenStable().then(() => {
                let element = this.fixture.nativeElement;
                this.fixture.detectChanges();
    
                expect(element.querySelectorAll('li').length).toBe(2);
            });
        }));
    
        it('should call the service on init', async(() => {
            this.fixture.whenStable().then(() => {
                spyOn(this.service, 'loadAll');
                this.fixture.detectChanges();
    
                expect(this.service.loadAll).toHaveBeenCalled();
            });
        }));
    });
    

    种子项目本身可以在https://github.com/froko/ng2-seed-webpack找到

    希望这会有所帮助。

    【讨论】:

    • 但是RC5 change log 还声明“ngModel 在更新时始终是异步的。这意味着在测试中,您需要使用ComponentFixture.whenStable,而不是调用ComponentFixture.detectChanges,这是异步的。”您已经在使用whenStable,但您仍在使用detectChanges。如果您现在只删除 this.fixture.detectChanges(),您的测试是否可能仍然有效?
    猜你喜欢
    • 2017-01-22
    • 2017-11-27
    • 2017-10-31
    • 1970-01-01
    • 2018-08-10
    • 2017-07-04
    • 2017-01-05
    • 2018-11-21
    • 2017-03-08
    相关资源
    最近更新 更多