2

考虑以下InjectionToken类型Foo

export const FOO = new InjectionToken<Foo>(
  'foo token',
  { factory: () => new Foo() });

现在假设我已经疯狂地瞄准了 100% 的测试覆盖率。为此,我必须对那个小factory功能进行单元测试。

我正在考虑创建一个在我的测试中只有一个提供者的注入器:

const inj = Injector.create({
  providers: [{ provide: FOO }] // compiler error here
});

const foo = inj.get(FOO);

expect(foo).toBeTruthy();

不幸的是,这会因编译器错误而失败,因为{ provide: FOO }它不是没有 、 或 属性的有效useValue提供useFactory程序useExisting。但是,当注入令牌带有自己的工厂时,为什么我不得不定义其中之一呢?

当然,我仍然尝试了所有选项:

  • useValue: FOO编译并运行,但似乎没有执行工厂方法
  • useFactory: () => FOO, deps: []也编译和运行,但似乎也没有执行工厂方法
  • useExisting: FOO编译,但在运行时因循环依赖错误而失败

有趣的是,文档中提供了一个类似的场景InjectionToken,但它没有显示我正在寻找的注册:

const MY_SERVICE_TOKEN = new InjectionToken<MyService>('Manually constructed MyService', {
  providedIn: 'root',
  factory: () => new MyService(inject(MyDep)),
});

// How is `MY_SERVICE_TOKEN` token provided?

const instance = injector.get(MY_SERVICE_TOKEN);

在 StackBlitz 上创建了一个示例,您可以自己尝试一下。

4

1 回答 1

1

当您为 指定factory函数时InjectionToken,令牌会自动在 root 中提供。因此,您也不需要在测试台中提供它。

为了在测试中使用此功能,您需要使用TestBed而不是仅使用Injector.create.

import { TestBed } from '@angular/core/testing';

describe('Foo', () => {
  beforeEach(() => TestBed.configureTestingModule({}));

  it('should be created', () => {
    const service: Foo = TestBed.get(FOO);
    expect(service).toBeTruthy();
  });
});

文档

创建 时InjectionToken,您可以选择指定一个工厂函数,该函数返回(可能通过创建)参数化类型的默认值T。这设置了InjectionToken使用这个工厂作为提供者,就好像它是在应用程序的根注入器中明确定义的一样。如果需要零参数的工厂函数需要注入依赖项,它可以使用该 inject函数来完成。请参阅下面的示例。

于 2019-11-11T10:17:39.677 回答