我正在构建一个将包装SignalR
库的客户端:
export class RealTimeCommunicator {
/** SignalR hub connection */
private hubConnection: HubConnection | null = null;
private buildConnection(url: string): HubConnection {
return new HubConnectionBuilder()
.withUrl(url)
.build();
}
public subscribe(onStart: () => void, success: (data: IVehicleInfo) => void, fail?: (err: Error) => void): () => void {
this.hubConnection = this.buildConnection("/someurl");
this.hubConnection.on("send", data => {
success(data);
});
this.hubConnection.start()
.then(onStart)
.catch(err => fail && fail(err));
return this.unsubscribe;
}
public subscribeToVehicleDetails(vehicleId: number, success: (data: IVehicleInfo) => void, fail?: (err: Error) => void): () => void {
return this.subscribe(() => this.hubConnection!.invoke("EnrolInVehicleGroupAsync", vehicleId), success, fail);
}
我想测试它,但是模拟SignalR
,所以我在解决方案中添加了__mocks__/@aspnet/signalr.ts
:
let SignalR = jest.genMockFromModule("@aspnet/signalr");
class HubConnection {
public on(methodName: string, callback: () => string): Promise<void> {
this.successCallback = callback;
return Promise.resolve()
}
public start(): Promise<void> { return Promise.resolve() }
public successCallback: () => string = () => "failure";
}
let hubConnection = new HubConnection();
let HubConnectionBuilder = () => ({
withUrl: (url) => ({
build: () => hubConnection
})
});
SignalR = {
HubConnectionBuilder: HubConnectionBuilder,
HubConnection: hubConnection
};
module.exports = SignalR;
我正在尝试监视on
方法以确保已被调用,并作为扩展目标确认我的成功处理程序已正确注册。
import { RealTimeCommunicator } from "./RealTimeCommunicator";
jest.mock('SignalR');
describe("RTC", () => {
test("foo", () => {
const ConnectionBuilder = require("SignalR").HubConnectionBuilder;
const connection = new ConnectionBuilder().withUrl("").build();
const spy = jest.spyOn(connection, 'on');
expect(spy).toHaveBeenCalled(); //Expectation fails
const successText = "success!";
const successCallBack: () => string = () => successText;
const rtc = new RealTimeCommunicator();
rtc.subscribeToVehicleDetails(1, successCallBack, _ => _);
expect(connection.successCallback()).toBe(successText); // connection.successCallback is undefined
})
});
如果我在SignalR
模拟中放置断点,则可以看到on
正在被调用,但间谍却看不到它。同样,我在模拟游戏上狂奔的successCallback
又回到了undefined
答案 0 :(得分:2)
您能提供任何可行的示例(例如以回购形式)重现您的问题吗?据我所知,所提供的代码段中存在一些缺陷。
首先,jest.mock('SignalR');
为何真正起作用? SignalR 不是应该抛出错误的模块。您应该模拟实际要导入的模块:jest.mock('@aspnet/signalr');
。除此之外,测试的第一部分包括测试第三方库-除了检查您的模拟程序是否正常工作之外,您为什么要这样做?
第二,您要检查创建间谍后on
方法是否被立即调用。但是,间谍只记录创建后的调用。您可能想要的是默认情况下使 on 方法成为间谍:
// in __mocks__/@aspnet/signalr.ts
class HubConnection {
public on = jest.fn().mockImplementation((methodName: string, callback: () => string) => {
this.successCallback = callback;
return Promise.resolve()
});
// ...
}
第三,您在测试中创建的连接与以后使用 subscribeToVehicleDetails 创建的连接不同,因此successCallback仍将返回“失败”如果可以的话。
答案 1 :(得分:0)
您已经接近,只需要进行两项更改即可。
返回success(data)
的结果:
public subscribe(onStart: () => void, success: (data: IVehicleInfo) => void, fail?: (err: Error) => void): () => void {
this.hubConnection = this.buildConnection("/someurl");
this.hubConnection.on("send", data => {
return success(data); // return the result
});
this.hubConnection.start()
.then(onStart)
.catch(err => fail && fail(err));
return this.unsubscribe;
}
等待断言spy
已被调用,直到之后您致电rtc.subscribeToVehicleDetails
:
const spy = jest.spyOn(connection, 'on');
const successText = "success!";
const successCallBack: () => string = () => successText;
const rtc = new RealTimeCommunicator();
rtc.subscribeToVehicleDetails(1, successCallBack, _ => _);
expect(spy).toHaveBeenCalled(); // SUCCESS
expect(connection.successCallback()).toBe(successText); // SUCCESS