You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 16:49:36