【问题标题】:Angular5 TestBed useValue seems not injecting same object instanceAngular5 TestBed useValue 似乎没有注入相同的对象实例
【发布时间】:2018-09-19 15:14:11
【问题描述】:

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

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

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 使用模拟实例?

【问题讨论】:

  • 您的 TestComponent 中哪里有 setTestProperty ?
  • 我没有。它只是被调用来为模拟实例 testInjectableMock.setTestProperty('valueInMock'); 设置新值;
  • 如果您再次检查示例,模拟实例上的 testProperty 将更改为新值。我希望在组件中注入模拟实例,但似乎不是。
  • 我编辑了问题并删除了 setter 以避免这种混淆。最初的问题仍然存在......
  • 对不起,我第一次看不太清楚...

标签: angular unit-testing angular5


【解决方案1】:

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

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

你应该改用工厂:

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

【讨论】:

  • 将此标记为已接受的答案,因为我们一直在同时使用工厂,并且按预期工作。
  • 我只是在 Angular 11 上遇到了这个问题。即使 10788 应该被修复,我也不得不使用 useFactory
【解决方案2】:

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

试试这个?

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

【讨论】:

    【解决方案3】:

    试试

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-11-21
      • 2019-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多