Angular 5中使用Jest模拟JavaScript对象的技术问题咨询
嘿,作为Angular和Jest的新手,我完全懂你在模拟第三方SDK对象时的迷茫——下面我会一步步带你搞定这个场景,针对你的MyService给出具体的测试方案:
哦对了,先提个小细节:你的代码里startService方法里调用的是setupService(),但私有方法实际定义的是setUpService()(大小写S的区别),这会导致运行时报错,测试前记得先修正这个拼写问题哦!
1. 先搞定AWS SDK的模拟
首先,我们需要在Jest中模拟aws-sdk里的CloudWatchLogs类,避免测试时真的调用AWS服务。可以用Jest的jest.mock来直接模拟整个模块:
// 在你的测试文件顶部 jest.mock('aws-sdk/clients/browser_default', () => ({ CloudWatchLogs: jest.fn().mockImplementation(() => ({ // 这里可以添加你需要用到的CloudWatchLogs方法的模拟实现,比如后续有调用logEvents之类的,就加在这里 })) }));
这样一来,当你的服务里创建new CloudWatchLogs()时,实际调用的是Jest的模拟函数,不会真的初始化AWS客户端。
2. 测试startService方法的行为
接下来我们要测试startService是否正确调用了setUpService和myOtherTask,同时验证setUpService是否正确初始化了cloudWatchLogs。
测试初始化逻辑
因为setUpService是私有方法,我们可以通过检查实例的cloudWatchLogs属性来验证它的执行效果:
import { MyService } from './my.service'; import { CloudWatchLogs } from 'aws-sdk/clients/browser_default'; describe('MyService', () => { let service: MyService; // 获取CloudWatchLogs的模拟构造函数 const mockCloudWatchLogs = CloudWatchLogs as jest.Mock; beforeEach(() => { // 重置模拟函数的调用记录 mockCloudWatchLogs.mockClear(); service = new MyService(); }); it('should initialize CloudWatchLogs when startService is called', () => { // 调用startService service.startService(); // 验证CloudWatchLogs的构造函数被调用了一次 expect(mockCloudWatchLogs).toHaveBeenCalledTimes(1); // 验证服务的cloudWatchLogs属性被正确赋值 expect(service['cloudWatchLogs']).toBeInstanceOf(mockCloudWatchLogs); }); it('should not re-initialize CloudWatchLogs if it already exists', () => { // 手动给cloudWatchLogs赋值,模拟已经初始化过的状态 service['cloudWatchLogs'] = {} as CloudWatchLogs; service.startService(); // 验证构造函数没有被调用(因为已经存在实例) expect(mockCloudWatchLogs).not.toHaveBeenCalled(); }); });
验证私有方法的调用
如果你想直接验证startService是否调用了setUpService和myOtherTask,可以用jest.spyOn结合TypeScript的类型断言来访问私有方法:
it('should call setUpService and myOtherTask when startService is invoked', () => { // 用spyOn监听私有方法,注意这里用类型断言绕过私有访问限制 const setUpSpy = jest.spyOn(service as any, 'setUpService'); const otherTaskSpy = jest.spyOn(service as any, 'myOtherTask'); service.startService(); expect(setUpSpy).toHaveBeenCalledTimes(1); expect(otherTaskSpy).toHaveBeenCalledTimes(1); });
3. 处理myOtherTask中的CloudWatchLogs调用
如果myOtherTask里调用了cloudWatchLogs的方法(比如describeLogStreams),你可以在模拟的CloudWatchLogs实例里添加对应的方法模拟,然后验证调用:
// 调整之前的mock,添加方法模拟 jest.mock('aws-sdk/clients/browser_default', () => ({ CloudWatchLogs: jest.fn().mockImplementation(() => ({ describeLogStreams: jest.fn().mockResolvedValue({ logStreams: [] }) })) })); // 测试myOtherTask的调用 it('should call describeLogStreams in myOtherTask', async () => { service.startService(); // 获取模拟的cloudWatchLogs实例 const mockLogsInstance = mockCloudWatchLogs.mock.instances[0]; // 假设myOtherTask是异步的,这里用await等待完成 await service['myOtherTask'](); expect(mockLogsInstance.describeLogStreams).toHaveBeenCalled(); });
内容的提问来源于stack exchange,提问作者user2477533

