角度测试-模拟InjectionToken [英] Angular Testing - Mocking An InjectionToken
问题描述
我正在尝试测试处理SignalR连接的Angular服务,该服务将SignalR的代码作为InjectionToken.
I'm trying to test an Angular service that handles SignalR connections, which takes the code for SignalR as an InjectionToken.
以下是提供者文件:
// signalr-provider.ts
import { InjectionToken } from '@angular/core';
export const SIGNALR_TOKEN = new InjectionToken('signalR');
export function signalRFactory() {
return window['signalR'];
}
export const SIGNALR_PROVIDER = [ { provide: SIGNALR_TOKEN, useFactory: signalRFactory } ];
这是服务:
// signalr-service.ts
import { Injectable, Inject } from '@angular/core';
import { SIGNALR_TOKEN } from './signalr-provider';
import { HubConnection } from '@aspnet/signalr';
import { environment } from '../../../environments/environment';
@Injectable()
export class SignalrService {
private hubConnection: HubConnection;
private baseUrl: string = environment.baseUrl;
constructor(@Inject(SIGNALR_TOKEN) private signalR: any) {
this.init();
}
init(): void {
this.hubConnection = new this.signalR.HubConnectionBuilder().withUrl(`${this.baseUrl}/hubs/test`).build();
}
}
令牌在应用模块中的提供方式如下:
The token is provided in the app module like this:
// From app.module.ts
@NgModule({
declarations: [...],
imports: [...],
providers: [ SIGNALR_PROVIDER, SignalrService ],
bootstrap: [ AppComponent]
})
export class AppModule {}
到目前为止,我没有运气试图在测试文件中模拟InjectionToken,并每次都以NullInjectorError: No provider for InjectionToken signalR!
消息结束.
So far, I'm having no luck trying to mock the InjectionToken in my test file, and end up with a NullInjectorError: No provider for InjectionToken signalR!
message every time.
这是我的第一次尝试,从signalRFactory函数返回一个仅包含初始连接所需属性的模拟对象:
Here's my first attempt, returning a mocked object from the signalRFactory function with only the properties needed in the initial connection:
// signalr-service.spec.ts
import { TestBed, async } from '@angular/core/testing';
import { InjectionToken } from '@angular/core';
import { SignalrService } from './signalr-service';
const SIGNALR_TOKEN = new InjectionToken('signalR');
function signalRFactory() {
return {
HubConnectionBuilder: () => {
return {
withUrl: (url) => {
return {
build: () => {}
};
}
};
}
};
}
const SIGNALR_PROVIDER = [ { provide: SIGNALR_TOKEN, useFactory: signalRFactory } ];
describe('ConnectionService', () => {
beforeEach(
async(() => {
TestBed.configureTestingModule({
providers: [ SIGNALR_PROVIDER, SignalrService ]
});
})
);
it('should exist', () => {
const connectionService = TestBed.get(SignalrService);
expect(connectionService).toBeTruthy();
});
});
在第二次尝试中,我将模拟对象分配给了一个变量:
In my second attempt, I assigned the mocked object to a variable:
import { TestBed, async } from '@angular/core/testing';
import { InjectionToken } from '@angular/core';
import { SignalrService } from './signalr-service';
const SIGNALR_TOKEN = new InjectionToken('signalR');
const SIGNALR_VALUE = {
HubConnectionBuilder: () => {
return {
withUrl: (url) => {
return {
build: () => {}
};
}
};
}
};
const SIGNALR_PROVIDER = [ { provide: SIGNALR_TOKEN, useValue: SIGNALR_VALUE } ];
describe('ConnectionService', () => {
beforeEach(
async(() => {
TestBed.configureTestingModule({
providers: [ SIGNALR_PROVIDER, SignalrService ]
});
})
);
it('should exist', () => {
const connectionService = TestBed.get(SignalrService);
expect(connectionService).toBeTruthy();
});
});
在我的第三次尝试中,我取出了SIGNALR_PROVIDER,并尝试通过工厂和直接值直接在providers数组中提供值:
In my third attempt, I took out the SIGNALR_PROVIDER and tried to provide the value directly in the providers array by factory and by direct value:
直接值:
import { TestBed, async } from '@angular/core/testing';
import { InjectionToken } from '@angular/core';
import { SignalrService } from './signalr-service';
const SIGNALR_TOKEN = new InjectionToken('signalR');
const SIGNALR_VALUE = {
HubConnectionBuilder: () => {
return {
withUrl: (url) => {
return {
build: () => {}
};
}
};
}
};
describe('ConnectionService', () => {
beforeEach(
async(() => {
TestBed.configureTestingModule({
providers: [ { provide: SIGNALR_TOKEN, useValue: SIGNALR_VALUE }, SignalrService ]
});
})
);
it('should exist', () => {
const connectionService = TestBed.get(SignalrService);
expect(connectionService).toBeTruthy();
});
});
工厂:
import { TestBed, async } from '@angular/core/testing';
import { InjectionToken } from '@angular/core';
import { SignalrService } from './signalr-service';
const SIGNALR_TOKEN = new InjectionToken('signalR');
function signalRFactory() {
return {
HubConnectionBuilder: () => {
return {
withUrl: (url) => {
return {
build: () => {}
};
}
};
}
};
}
describe('ConnectionService', () => {
beforeEach(
async(() => {
TestBed.configureTestingModule({
providers: [ { provide: SIGNALR_TOKEN, useFactory: signalRFactory }, SignalrService ]
});
})
);
it('should exist', () => {
const connectionService = TestBed.get(SignalrService);
expect(connectionService).toBeTruthy();
});
});
每次尝试仍然给我NullInjectorError: No provider for InjectionToken signalR!
我被卡住了.很明显,我不了解InjectionToken.有人能指出我正确的方向吗?
Each attempt still gives me NullInjectorError: No provider for InjectionToken signalR!
I'm stuck. There's obviously something I don't know about the InjectionToken. Could anyone point me in the right direction?
推荐答案
弄清楚了-我的问题是我在测试文件中重新定义了令牌,因此我的测试是为模拟对象提供与令牌完全不同的令牌.我的服务所期望的.将其更改为此可解决的问题:
Figured it out--my problem was that I redefined the token in the test file, so my test was providing my mocked object for a completely different token than the one my service was expecting. Changing it to this fixed it:
// signalr-service.spec.ts
import { TestBed, async } from '@angular/core/testing';
import { InjectionToken } from '@angular/core';
import { SignalrService } from './signalr-service';
import { SIGNALR_TOKEN } from './signalr-provider'; // This is the change
function signalRFactory() {
return {
HubConnectionBuilder: () => {
return {
withUrl: (url) => {
return {
build: () => {}
};
}
};
}
};
}
const SIGNALR_PROVIDER = [ { provide: SIGNALR_TOKEN, useFactory: signalRFactory } ];
describe('ConnectionService', () => {
beforeEach(
async(() => {
TestBed.configureTestingModule({
providers: [ SIGNALR_PROVIDER, SignalrService ]
});
})
);
it('should exist', () => {
const connectionService = TestBed.get(SignalrService);
expect(connectionService).toBeTruthy();
});
});
这篇关于角度测试-模拟InjectionToken的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!