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

Angular5 TestBed useValue seems not injecting same object instance

在编写单元测试时遇到奇怪的情况,我不明白问题出在哪里。

我已经准备好重现的短代码:

TestInjectable - 简单的注射剂 class

@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 我希望组件会 return 这个值。问题是组件 returning testValue 这是默认值,测试失败:

Expected 'testValue' to be 'valueInMock'.

听起来 TestBed 正在创建 TestInjectable 的另一个实例,即使我使用 useValue 属性.

提供了实例
providers: [{provide: TestInjectable, useValue: testInjectableMock}]

有谁知道我是否遗漏了什么或问题在哪里以及如何说服 TestBed 使用模拟实例?

尝试

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');
  });
});

我怀疑即使使用 useValue,您也没有得到未受污染的 testInjectableMock 版本。

试试这个?

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

Angular DI 克隆了 useValue 提供的对象,从外观上看,是否错误:

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

您应该改用工厂:

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