Angular Jasmine测试中如何让OrdersService复用ItemsService的同一实例?
Angular Jasmine测试中如何让OrdersService复用ItemsService的同一实例?
嘿,我来帮你搞定这个问题!你需要在OrdersService的测试中,确保它使用的ItemsService实例和你手动操作的是同一个,这样就能共享已添加的商品数据了。下面是具体的解决步骤和修改后的测试代码:
问题根源
你原来的OrdersService测试代码里没有正确处理依赖:既没有注入ItemsService,也没有确保OrdersService能拿到有效的ItemsService实例,直接调用itemsService.getItems()[0]肯定会报错,因为这个实例根本没被初始化。
解决方法
在Angular的TestBed测试环境中,同一个测试模块配置下的服务是单例的。我们只需要在测试中同时获取OrdersService和ItemsService的实例,就能保证它们用的是同一个ItemsService对象。
修改后的完整测试代码
import { TestBed } from '@angular/core/testing'; import { OrdersService } from './orders.service'; // 1. 先导入ItemsService import { ItemsService } from '../items/items.service'; describe('OrdersService', () => { let service: OrdersService; // 2. 声明ItemsService变量 let itemsService: ItemsService; beforeEach(() => { TestBed.configureTestingModule({ // 3. 显式提供两个服务,确保TestBed能正确解析依赖 providers: [OrdersService, ItemsService] }); // 4. 同时获取两个服务的实例,它们会共享同一个ItemsService单例 service = TestBed.inject(OrdersService); itemsService = TestBed.inject(ItemsService); }); it('should be created', () => { expect(service).toBeTruthy(); }); it('should create order from existing item', async () => { // 第一步:先通过ItemsService添加测试商品 const testItem = { id: '123', name: 'Test Item', baseUnit: 'unit', brand: 'brand', price: 100, quantity: 10, supplier: 'supplier', cost: 50, imageUrl: 'url', }; itemsService.insertItem(testItem); // 第二步:调用OrdersService的方法创建订单 const newOrder = await service.insertOrder(itemsService.getItems()[0]); // 第三步:添加你的断言逻辑,比如验证订单是否正确创建 expect(newOrder).toBeTruthy(); // 假设你的订单对象包含商品ID,这里可以断言匹配 expect(newOrder.itemId).toBe(testItem.id); // 还可以验证订单列表里是否包含这个新订单(如果OrdersService有getOrders方法的话) // const orders = service.getOrders(); // expect(orders).toContain(newOrder); }); });
额外说明
如果你不想使用ItemsService的真实实现(比如想隔离测试,只验证依赖交互),可以用Jasmine的模拟对象来替代真实服务,示例如下:
beforeEach(() => { // 创建模拟的ItemsService,只提供我们需要的方法 const mockItemsService = jasmine.createSpyObj('ItemsService', ['getItems']); // 预设getItems的返回值 mockItemsService.getItems.and.returnValue([ { id: '123', name: 'Mock Item' } ]); TestBed.configureTestingModule({ providers: [ OrdersService, { provide: ItemsService, useValue: mockItemsService } ] }); service = TestBed.inject(OrdersService); });
这种方式适合测试OrdersService和ItemsService的交互逻辑,而不需要关心ItemsService内部的实现细节。
备注:内容来源于stack exchange,提问作者Kadiem Alqazzaz
相关产品推荐
相关产品推荐

