Angular 4.のプロバイダーでコンポーネントをモックするのに問題があります。以下にコードを示します。
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/core/platform-browser';
import { DebugElement } from '@angular/core';
import { FormsModule,
ReactiveFormsModule,
FormBuilder
} from '@angular/forms';
import { Router, RouterModule } from '@angular/router';
import {
Http, ConnectionBackend,
BaseRequestOptions
} from '@angular/http';
import { MockBackend, async } from '@angular/http/testing';
import { LoginComponent } from './../../../src/app/login/login.component';
import { LoginService } from './../../../src/app/login/login.service';
import { LoginComponent } from './../../../src/app/login/login.component';
import { LoggerService } from './../../../src/app/logger-service';
import { AuthService } from './../../../src/app/pages/auth.service';
describe('LoginComponent', () => {
let comp: LoginComponent;
let fixture: ComponentFixture<LoginComponent>;
let de: DebugElement;
let el: HTMLElement;
beforeEach(() => {
// implement mock
class loggerService = {
};
class loginService = {
};
class authService = {
};
class router = {
};
TestBed.configureTestingModule({
declarations: [ LoginComponent ],
imports: [
ReactiveFormsModule,
FormsModule
],
providers: [
MockBackend,
BaseRequestOptions,
AuthService,
LoginService,
LoggerService,
RouterModule,
{ provide: AuthService, useValue: authService },
{ provide: LoginService, useClass: LoginService },
{ provide: LoggerService, useValue: loggerService },
{
provide: Http, useFactory: (backend: ConnectionBackend,
defaultOptions: BaseRequestOptions) => {
return new Http(backend, defaultOptions);
}, deps: [MockBackend, BaseRequestOptions]
},
{ provide: Router, useClass: router }
]
}).compileComponents().then(() => {
fixture = TestBed.createComponent(LoginComponent);
comp = fixture.componentInstance;
comp.detectChanges();
comp.ngOnInit();
loginService = fixture.debugElement.injector.get(LoginService);
loggerService = fixture.debugElement.injector.get(LoggerService);
authService = fixture.debugElement.injector.get(AuthService);
router = fixture.debugElement.injector.get(Router);
});
});
it('should create component', async(() => {
expect(comp).toBeDefined();
}));
});
ここに私のエラーがあります:
spec-bundle.js:9未処理のPromiseの拒否:AuthServiceのプロバイダーがありません! ;ゾーン:ProxyZone;タスク:Promise.then;値:エラー{__zone_symbol__error:Error.ZoneAwareErrorでのエラー( http:// localhost:9876/base/config/spec-bundle.js:9:3748709 )a……}
私が間違っていることについてのアイデアはありますか?
前もって感謝します :)
それで、いくつかのことが飛び出してきました。彼らがあなたの問題かどうかはわかりません。
空のクラスをスタブ化し、それらを使用して実際のサービスの代わりにコンポーネントにモックインジェクトし、それらのインジェクションされたサービスをスタブ変数に割り当てようとしています。代わりに、合法的なサービスを使用するか、それらをスタブしてそれらへの別の参照を取得しようとします。
AuthServiceの場合、実際のサービスを提供したい場合(後でその部分を傍受してスパイしたとしても)、あなたはただ言うことができます
...
providers: [AuthService]
...
モックしたい場合は、次を使用します。
class mockAuthService{}
beforeEach(() => {
TestBed.configureTestingModule({
...
providers: [{provide: AuthService, useClass: mockAuthService}]
...
または
let mockAuthService;
beforeEach(() => {
mockAuthService = {}
TestBed.configureTestingModule({
...
providers: [{provide: AuthService, useValue: mockAuthService}]
...
また、これが問題であることを再確認することはできません。これをすべてbeforeEachスコープ内で実行し、外部ではありませんでした(したがって、必要に応じて後でこれらの変数を参照できます)。上/下に示したように、それをbeforeEach()の上に移動します。
ここに私が言っていることの例があります。
describe('LoginComponent', () => {
let comp: LoginComponent;
let fixture: ComponentFixture<LoginComponent>;
let de: DebugElement;
let el: HTMLElement;
let authServiceReference;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [ LoginComponent ],
imports: [
ReactiveFormsModule,
FormsModule
],
providers: [
MockBackend,
BaseRequestOptions,
AuthService,
LoginService,
LoggerService,
RouterModule,
{
provide: Http, useFactory: (backend: ConnectionBackend,
defaultOptions: BaseRequestOptions) => {
return new Http(backend, defaultOptions);
}, deps: [MockBackend, BaseRequestOptions]
},
Router
]
}).compileComponents().then(() => {
fixture = TestBed.createComponent(LoginComponent);
comp = fixture.componentInstance;
comp.detectChanges();
comp.ngOnInit();
authServiceReference = Testbed.get(AuthService); // get service you injected above
});
});
it('should create component', () => {
expect(comp).toBeDefined();
}); // this part really doesn't need to be async.
いくつかの追加事項(私も比較的新しく、これらは私が取り上げたものです)。テスト自体で、挿入されたサービスへの参照を取得するだけで、混乱が少なくなります。例:
it('should have a service', inject([SomeService], (serviceHandle: SomeService) => {
expect(serviceHandle).toEqual(sameServiceYouTriedToGrabInInitialSetUp);
}
それが理にかなっていることを願っています。要するに、そこにあるものをつかむほうがずっと簡単です。さらに、that特定のテストのためにハンドルを取得したい数のサービスを注入できます。
it('should have a service', inject([SomeService, SomeOtherService, YetOneMoreService], (serviceHandle: SomeService, otherServiceHandle: SomeOtherService, yetAnotherHandle: YetOneMoreService) => {
spyOn(serviceHandle, 'isAuthenticated').and.returnsValue(true);
spyOn(otherServiceHandle, 'getUrl').and.returnsValue(/home);
let yahSpy = spyOn(yetAnotherHandle, 'doSomething');
//code
expect (yahSpy.doSomething).toHaveBeenCalled();
}
お役に立てれば。