rxjs - Nest.js 处理 HttpService 的错误

标签 rxjs axios nestjs

我正在尝试测试 NestJS 内置的 HttpService(基于 Axios)。不过,我在测试错误/异常状态时遇到了麻烦。在我的测试套件中,我有:

let client: SomeClearingFirmClient;

  const mockConfigService = {
    get: jest.fn((type) => {
      switch(type) {
        case 'someApiBaseUrl': {
          return 'http://example.com'
        }
        case 'someAddAccountEndpoint': {
          return '/ClientAccounts/Add';
        }
        case 'someApiKey': {
          return 'some-api-key';
        }

        default:
          return 'test';
      }
    }),
  };

  const successfulAdd: AxiosResponse = {
    data: {
      batchNo: '39cba402-bfa9-424c-b265-1c98204df7ea',
      warning: '',
    },
    status: 200,
    statusText: 'OK',
    headers: {},
    config: {},
  };

  const failAddAuth: AxiosError = {
    code: '401',
    config: {},
    name: '',
    message: 'Not Authorized',
  }

  const mockHttpService = {
    post: jest.fn(),
    get: jest.fn(),
  }

  it('Handles a failure', async () => {
    expect.assertions(1);
    mockHttpService.post = jest.fn(() => of(failAddAuth));

    const module: TestingModule = await Test.createTestingModule({
      providers: [
        {
          provide: ConfigService,
          useValue: mockConfigService,
        },
        {
          provide: HttpService,
          useValue: mockHttpService,
        },
        SomeClearingFirmClient,
      ],
    }).compile();

    client = module.get<SomeClearingFirmClient>(SomeClearingFirmClient);

    const payload = new SomeClearingPayload();
    try {
      await client.addAccount(payload);
    } catch(e) {
      console.log('e', e);
    }
  });

我的实现是:

async addAccount(payload: any): Promise<SomeAddResponse> {
    const addAccountEndpoint = this.configService.get('api.someAddAccountEndpoint');
    const url = `${this.baseUrl}${addAccountEndpoint}?apiKey=${this.apiKey}`;
    const config = {
      headers: {
        'Content-Type': 'application/json',
      }
    };

    const response = this.httpService.post(url, payload, config)
      .pipe(
        map(res => {
          return res.data;
        }),
        catchError(e => {
          throw new HttpException(e.response.data, e.response.status);
        }),
      ).toPromise().catch(e => {
        throw new HttpException(e.message, e.code);
      });

    return response;
  }

无论我使用 Observables 还是 Promises,我都无法捕捉到任何东西。 4xx 级错误成功通过。我觉得我记得 Axios 添加了某种配置选项来拒绝/向失败的订阅者发送 Observable 错误......但我可以想象这一点。我在测试工具中做错了吗?我见过的其他 StackOverflow 帖子似乎说通过 catchError 管道应该可以解决问题,但我的错误是通过 map 运算符。

最佳答案

您的mockHttpService 似乎没有返回错误,但返回了一个值:

mockHttpService.post = jest.fn(() => of(failAddAuth));

of(failAddAuth) 所做的是发出一个值 (failAddAuth) 然后完成。

这就是为什么永远不会到达 this.httpService.post(url, payload, config) 中的 catchError,因为没有错误发生。

为了确保 catchError 被命中,post() 返回的 observable 必须发出一个错误通知

你可以试试这个:

// Something to comply with `HttpException`'s arguments
const err = { response: 'resp', status: '4xx' };

mockHttpService.post = jest.fn(() => throwError(err));

throwError(err)new Observable(s => s.error(err))( Source code ) 相同。

关于rxjs - Nest.js 处理 HttpService 的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61742615/

相关文章:

javascript - NestJS 环境变量未定义

angular - 表格: Manually trigger valueChange

angular - 为什么没有 RxJS 运算符来从流中删除特定项目?

javascript - 如何通过重新连接实现 shareReplay?

javascript - 是否可以在created()完成后运行v-for?

vue.js - vue-typeahead 说你需要提供一个 HTTP 客户端

typescript - NestJS - 避免返回用户密码

angular - 在主题 angular2 错误上使用 throttleTime 函数

javascript - 如何使用 axios 分页从 firebase 获取批量数据?

postgresql - 无法将 SSL 安全数据库连接到 typeorm