Angular5 TestBed useValue似乎未注入相同的对象实例

时间:2018-09-19 15:14:11

标签: angular unit-testing angular5

在编写单元测试时,我遇到了一个奇怪的案例,我不知道问题出在哪里。

我已经准备了用于复制的短代码:

TestInjectable-简单的可注入类

@Injectable()
class TestInjectable {
  testProperty = 'testValue';
}

TestComponent-使用TestInjectable

的小组件
@Component({
  providers: [TestInjectable],
  template: ''
})
class TestComponent {
  constructor(private injectable: TestInjectable) {
  }

  doTest() {
    return this.injectable.testProperty;
  }
}

单元测试

describe('Test TestComponent', () => {
  beforeEach(async(() => {
    let testInjectableMock: TestInjectable = new TestInjectable();
    testInjectableMock.testProperty = 'valueInMock';

    TestBed.configureTestingModule({
      providers: [{provide: TestInjectable, useValue: testInjectableMock}],
      declarations: [TestComponent]
    }).compileComponents();
  }));

  it('should do something', () => {
    let fixture: ComponentFixture<TestComponent> = TestBed.createComponent(TestComponent);
    let component: TestComponent = fixture.componentInstance;

    expect(component.doTest()).toBe('valueInMock');
  });
});

由于我将testInjectableMock设置为valueInMock,因此我希望该组件将返回该值。问题在于组件返回的是默认值testValue,测试失败并显示以下信息:

  

预计“ testValue”为“ valueInMock”。

即使我使用TestBed属性提供实例,听起来TestInjectable仍在创建useValue的另一个实例。

providers: [{provide: TestInjectable, useValue: testInjectableMock}]

有人知道我是否错过了某件事,或者是抓住了什么,以及如何说服TestBed使用模拟实例吗?

3 个答案:

答案 0 :(得分:0)

尝试

describe('Test TestComponent', () => {
  let testInjectableMock: TestInjectable = new TestInjectable();

  beforeEach(async(() => {   
    TestBed.configureTestingModule({
      providers: [{provide: TestInjectable, useValue: testInjectableMock}],
      declarations: [TestComponent]
    }).compileComponents();
  }));

  it('should do something', () => {
    let fixture: ComponentFixture<TestComponent> = TestBed.createComponent(TestComponent);
    let component: TestComponent = fixture.componentInstance;
    testInjectableMock.testProperty = 'valueInMock';
    expect(component.doTest()).toBe('valueInMock');
  });
});

答案 1 :(得分:0)

我怀疑即使使用useValue,您也不会获得testInjectableMock的不变版本。

尝试一下?

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      providers: [{provide: TestInjectable, useValue: new TestInjectable()}],
      declarations: [TestComponent]
    }).compileComponents().then(() => {
      const testInjectableMock = TestBed.get(TestInjectable);
      testInjectableMock.setTestProperty('valueInMock');
    });
  }));

答案 2 :(得分:0)

Angular DI会克隆useValue提供的对象,并且从其外观来看,这样做是否正确:

https://github.com/angular/angular/issues/10788

您应该改用Factory:

TestBed.configureTestingModule({
  providers: [{provide: TestInjectable, /*-->*/ useFactory: () => testInjectableMock}],
  declarations: [TestComponent]
}).compileComponents();