如何提供具有自己的“工厂”的“InjectionToken”?
How to provide an `InjectionToken` that has its own `factory`?
考虑以下 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
编译,但在运行时因循环依赖错误而失败
有趣的是,在 the documentation 中为 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);
我创建了一个example on StackBlitz所以你可以自己试试。
当您为 InjectionToken
指定 factory
函数时,将自动在 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();
});
});
The docs 说
When creating an InjectionToken
, you can optionally specify a
factory function which returns (possibly by creating) a default value
of the parameterized type T
. This sets up the InjectionToken
using
this factory as a provider as if it was defined explicitly in the
application's root injector. If the factory function, which takes zero
arguments, needs to inject dependencies, it can do so using the
inject
function. See below for an example.
考虑以下 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
编译,但在运行时因循环依赖错误而失败
有趣的是,在 the documentation 中为 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);
我创建了一个example on StackBlitz所以你可以自己试试。
当您为 InjectionToken
指定 factory
函数时,将自动在 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();
});
});
The docs 说
When creating an
InjectionToken
, you can optionally specify a factory function which returns (possibly by creating) a default value of the parameterized typeT
. This sets up theInjectionToken
using this factory as a provider as if it was defined explicitly in the application's root injector. If the factory function, which takes zero arguments, needs to inject dependencies, it can do so using theinject
function. See below for an example.