Jasmine测试参数不匹配:如何Mock loadData与EventProvider类型的this?
Jasmine测试:Mock函数与EventProvider实例匹配问题
问题场景
控制器代码片段
const account = "abc", isIDValid = true, loadData = this.loadData, that = this; let args = {account, isIDValid, loadData, that}; dialog.open(args);
测试用例代码
describe("when user click open dialog", function() { let account, isIDValid, loadData, that, args; beforeEach(function() { account = "abc"; isIDValid = true; loadData = function() {}; that = folder1.project.Controller; args = {account, isIDValid, loadData, that}; }); it("should call dialog with args", function() { controller.abc(isIDValid); expect(dialog.open).toHaveBeenCalledWith(args); }); });
报错信息
Expected spy open to have been called with: [ Object({ account: 'abc', isIDValid: true, loadData: Function, that: Function }) ] but actual calls were: [ Object({ account: 'abc', isIDValid: true, loadData: Function, that: EventProvider folder1.project.Controller }) ].
解决方案
问题核心是测试中mock的loadData和that与控制器实际传递的引用/实例不匹配,调整方式如下:
1. 正确Mock loadData函数
不要单独定义空函数,直接Spy控制器实例上的loadData方法,确保测试使用的loadData和控制器里this.loadData是同一个引用:
spyOn(controller, 'loadData').and.callFake(function() {});
2. 匹配EventProvider类型的this
控制器里的that = this指向的是控制器的实例(EventProvider类型),测试中错误赋值为构造函数folder1.project.Controller,需改为使用控制器实例本身,或模拟一个符合EventProvider结构的实例。
修改后的测试用例示例
方案一:使用真实控制器实例
describe("when user click open dialog", function() { let args; beforeEach(function() { // Spy控制器实例的loadData方法 spyOn(controller, 'loadData').and.callFake(function() {}); // 使用控制器实例作为that(与控制器内的this一致) const that = controller; args = { account: "abc", isIDValid: true, loadData: controller.loadData, that: that }; }); it("should call dialog with args", function() { controller.abc(true); expect(dialog.open).toHaveBeenCalledWith(args); }); });
方案二:模拟EventProvider实例
describe("when user click open dialog", function() { let mockController, args; beforeEach(function() { // 创建模拟的EventProvider实例,包含loadData方法 mockController = jasmine.createSpyObj('EventProvider', ['loadData']); mockController.loadData.and.callFake(function() {}); args = { account: "abc", isIDValid: true, loadData: mockController.loadData, that: mockController }; // 注入mock实例到控制器(根据实际初始化逻辑调整) controller = new folder1.project.Controller(mockController); }); it("should call dialog with args", function() { controller.abc(true); expect(dialog.open).toHaveBeenCalledWith(args); }); });
内容的提问来源于stack exchange,提问作者JustMari
相关产品推荐
相关产品推荐

