У меня есть компонент с подписью:
constructor(private loremApiService: LoremApiService,
private ipsumService: IpsumService,
private dolorService: DolorService,
@Inject('sitService') private sitService: library.service.Service) {
}
Файл спецификации для компонента настроен с помощью:
let component: PowerBiReportComponent;
let fixture: ComponentFixture<TestingComponent>;
const mockLoremApi = { methodThatIsCalled: () => {} };
const mockIpsumService = { };
const mockSitService = { };
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ TestingComponent ],
schemas: [ CUSTOM_ELEMENTS_SCHEMA ],
providers: [
{ provide: LoremApiService, useValue: mockLoremApi },
{ provide: IpsumService, useValue: mockIpsumService },
UnmockedService,
{ provide: library.service.Service, useValue: mockSitService }
]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(TestingComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
Однако поставщик не используется из-за декоратора @Inject, тест не выполняется при запуске с:
Error: StaticInjectorError(DynamicTestModule)[sitService]:
StaticInjectorError(Platform: core)[sitService]:
NullInjectorError: No provider for sitService!
Как заставить TestingModule использовать mockSitService, несмотря на то, что в компоненте он @Injection?
@DanielWStrimpel К сожалению, неанонимный сервис импортируется с import * as library from 'sit-library';, поэтому я не могу быть таким конкретным. Кроме того, к сожалению, фактический Тип службы называется Service.
Все, что находится в @Inject(...), должно быть тем, что указано как свойство provide. Более новые версии Angular требуют (или настоятельно рекомендуют?), Чтобы это были токены для инъекций angular.io/guide/dependency-injection#injectiontoken
@DanielWStrimpel Аааа, я изменил объект предоставления в тесте, чтобы он соответствовал методу инъекции в родительском модуле компонента. Теперь это ошибка с [object ErrorEvent] thrown, которая может быть частью фактического тестового кода, который не работает из-за нереализованного макета. Это может решить проблему
проверьте мой ответ здесь stackoverflow.com/a/49842183/4399281 вы можете найти пример имитации службы
@DanielWStrimpel Если вы добавите обеспечение соответствия токенов инъекций в модуле компонента и TestModule в качестве configureTestingModule в качестве ответа, я приму это





Как указано в комментариях, Angular требует, чтобы любой токен в @Inject(...) был таким же, как и тот, который указан для свойства provide при настройке службы с DI Angular. Это также означает, что токен внедрения должен быть экспортирован за пределы модуля, чтобы другие могли использовать синтаксис @Inject().
Если услуга предоставляется так:
@NgModule({
providers: [
{ provide: SERVICE_TOKEN, useClass: Service }
]
})
Затем @Inject() должен быть настроен следующим образом (с использованием того же токена инъекции):
constructor(@Inject(SERVICE_TOKEN) private service: Service) {
}
Итак, в своем тесте вы имитируете это через (опять же, используя тот же токен инъекции):
beforeEach(async(() => {
TestBed.configureTestingModule({
providers: [
{ provide: SOME_TOKEN, useValue: mockService }
]
})
.compileComponents();
}));
Для получения дополнительной информации о токенах внедрения обратитесь к Документы по Angular.
Что делать, если у вас есть модуль, который использует forRoot для своих вводимых токенов, и вы хотите протестировать одну из служб внутри него, которая использует введенный токен? MyModule.forRoot(MyModuleConstants) имеет служебный MyModuleService и имеет constructor(@Inject(MyInjectionToken) constants)
useClass вместо useValue?
@GaoShenghan синтаксис зависит от того, что вы предоставляете. При настройке в модуле он использует useClass, поэтому Angular создает экземпляр для вас. В тесте OP имеет переменные, которые являются экземплярами зарезервированных сервисов, поэтому для них вы должны использовать версию useValue синтаксиса provide.
Пробовали делать:
{ provide: 'sitService', useValue: mockSitService }?