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

NestJS Service的HTTP请求方法单元测试如何实现全覆盖?

如何实现NestJS Service中HTTP请求方法的单元测试全覆盖?

你的问题核心在于没有正确处理Observable的异步特性,以及错误场景的断言逻辑和nock的错误抛出方式不匹配,导致map和throwError的代码行没被覆盖。下面我会一步步帮你修正测试代码,实现100%的代码覆盖。

问题分析

  1. 成功场景测试的异步问题:你原来的测试中,subscribe是异步执行的,但测试函数会直接结束,不会等待回调执行,导致map(response => response.data)的代码根本没机会运行,自然不会被覆盖。
  2. 错误场景的断言不匹配:nock的replyWithError默认抛出的是Error对象,而非字符串,但你的断言是expect(err).toBe('request failed'),这会导致断言失败,错误回调的逻辑没被正确触发,进而throwError的代码没被覆盖。

修正后的测试代码

首先,确保你导入了RxJS的lastValueFrom(RxJS 7+推荐用这个方法获取Observable的最终值):

import { lastValueFrom } from 'rxjs';

1. 成功场景测试(覆盖map行)

用async/await配合lastValueFrom等待Observable完成,确保map操作符的代码被执行:

describe('getEntries method', () => { 
  it('should send GET request and return entries', async () => { 
    // 拦截目标请求,返回模拟数据
    nock('http://localhost:3000') 
      .get('/v1/entries') 
      .reply(200, { data: require('../mocks/entries.json') }); 

    // 等待Observable完成,获取结果
    const result = await lastValueFrom(service.getEntries()); 
    // 断言结果匹配模拟数据
    expect(result).toEqual(require('../mocks/entries.json')); 
  }); 

2. 错误场景测试(覆盖throwError行)

调整错误断言逻辑,匹配nock抛出的Error对象,同时用expect.rejects简化错误捕获:

it('should throw error when request fails', async () => { 
    // 用Error对象抛出错误,和nock的默认行为一致
    nock('http://localhost:3000') 
      .get('/v1/entries') 
      .replyWithError(new Error('request failed')); 

    // 断言Observable会抛出指定错误
    await expect(lastValueFrom(service.getEntries())).rejects.toThrow('request failed'); 
  }); 
});

如果你的业务场景需要处理HTTP状态码错误(比如500、404),而不是网络错误,可以这样写测试:

it('should handle HTTP errors', async () => { 
  nock('http://localhost:3000') 
    .get('/v1/entries') 
    .reply(500, { message: 'Internal Server Error' }); 

  await expect(lastValueFrom(service.getEntries())).rejects.toMatchObject({
    status: 500,
    message: 'Internal Server Error'
  }); 
});

额外注意事项

  • 确保nock拦截的URL和实际请求的URL完全一致:检查this.apiHost是否确实是http://localhost:3000,HREF.entries是否是/v1/entries,任何路径或主机的不匹配都会导致nock无法拦截请求。
  • 如果你用的是Jest,确保测试模块正确注入了HttpService:在测试的Test.createTestingModule中导入HttpModule,或者用jest.mock模拟HttpService(不过用nock的话,直接用真实的HttpService即可)。

内容的提问来源于stack exchange,提问作者Lukas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 14:37:27