首页 > 解决方案 > 如何提供具有自己的“工厂”的“InjectionToken”?

问题描述

考虑以下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。但是,当注入令牌带有自己的工厂时,为什么我不得不定义其中之一呢?

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

有趣的是,文档中提供了一个类似的场景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 上创建了一个示例,您可以自己尝试一下。

标签: angularangular-dependency-injection

解决方案


当您为 指定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函数来完成。请参阅下面的示例。


推荐阅读