首页 > 解决方案 > 如何在具有私有方法的 Jest 中模拟 http 方法

问题描述

我正在为如何模拟以下功能而苦苦挣扎。我需要模拟这两种方法:getAllBookInCategorydeleteBookInCategory

公共方法调用私有方法,我假设我不必测试私有方法,只调用公共方法并验证私有方法被调用。这是对的吗?

公共方法getAllBookInCategorydeleteBookInCategory

私有方法makeRequest

import rp from "request-promise-native";

export class BookService {

@param bookCategory id of book category
@param boooks list of books

public static async getAllBookInCategory(bookCategory: string) {

        try {
            const neededInfo = {
                url: `https://${process.env.BOOK_HOST}/bookapi/${process.env.BOOKAPI_VERSION}/iterative/bookCategory/${ bookCategory }/books/all `,
                method: 'GET',
            }

            const result = await BookService.makeRequest(bookCategory, neededInfo);

            return rp(result);
        } catch(error) {
            Console.log(`Failed to get All Books in given category ${error}`)
        }
    }



public static async deleteBookInCategory(bookCategory: string, books: string[]) {

        try{
            const neededInfo = {
                url: `https://${process.env.BOOK_HOST}/bookapi/${process.env.BOOKAPI_VERSION}/ iterative /bookCategory/${ bookCategory }/books/bookDelete?books=${books.join()}`,
                method: 'DELETE',
            }

            const result = await BookService.makeRequest(bookCategory, neededInfo);

            return rp(result);
        } catch(error) {
            Console.log(`Failed to delete books from category: ${error}`)
        }
    }




private static async makeRequest(bookCategory: string, neededInfo: any, bodydata?: any) {

        const authValue = await BookService.getAuthValue(bookCategory, neededInfo);

        return {
            method: neededInfo.method,
            url: neededInfo.url,
            headers: {
                Host: process.env.BOOK_HOST,
                Authorization: authValue,

            },
            body: bodydata,
            json: true
        };
    }
}

标签: javascripttypescriptunit-testingmockingjestjs

解决方案


这是方法的单元测试解决方案getAllBookInCategory。您的代码有问题,您应该使用return await rp(result)而不是使用return rp(result).

BookService.ts

import rp from 'request-promise-native';

export class BookService {
  public static async getAllBookInCategory(bookCategory: string) {
    try {
      const neededInfo = {
        url: `https://${process.env.BOOK_HOST}/bookapi/${process.env.BOOKAPI_VERSION}/iterative/bookCategory/${bookCategory}/books/all`,
        method: 'GET',
      };

      const result = await BookService.makeRequest(bookCategory, neededInfo);

      return await rp(result);
    } catch (error) {
      console.log(`Failed to get All Books in given category ${error}`);
    }
  }

  public static async deleteBookInCategory(bookCategory: string, books: string[]) {
    try {
      const neededInfo = {
        url: `https://${process.env.BOOK_HOST}/bookapi/${
          process.env.BOOKAPI_VERSION
        }/iterative/bookCategory/${bookCategory}/books/bookDelete?books=${books.join()}`,
        method: 'DELETE',
      };

      const result = await BookService.makeRequest(bookCategory, neededInfo);

      return rp(result);
    } catch (error) {
      console.log(`Failed to delete books from category: ${error}`);
    }
  }

  private static async makeRequest(bookCategory: string, neededInfo: any, bodydata?: any) {
    const authValue = await BookService.getAuthValue(bookCategory, neededInfo);

    return {
      method: neededInfo.method,
      url: neededInfo.url,
      headers: {
        Host: process.env.BOOK_HOST,
        Authorization: authValue,
      },
      body: bodydata,
      json: true,
    };
  }

  private static async getAuthValue(catetory, info) {
    return 'authvalue';
  }
}

BookService.test.ts

import { BookService } from './BookService';
import rp from 'request-promise-native';

jest.mock('request-promise-native', () => jest.fn());

describe('BookService', () => {
  afterEach(() => {
    jest.resetAllMocks();
    jest.restoreAllMocks();
  });
  describe('#getAllBookInCategory', () => {
    beforeEach(() => {
      process.env.BOOK_HOST = 'example.com';
      process.env.BOOKAPI_VERSION = 'v1';
    });
    afterEach(() => {
      process.env.BOOK_HOST = '';
      process.env.BOOKAPI_VERSION = '';
    });
    it('should make request correctly', async () => {
      const mAuthvalue = 'mocked auth value';
      jest.spyOn(BookService as any, 'getAuthValue').mockResolvedValueOnce(mAuthvalue);
      const mResponse = 'success';
      rp.mockResolvedValueOnce(mResponse);
      const actual = await BookService.getAllBookInCategory('programming');
      expect(actual).toEqual(mResponse);
      expect(rp).toBeCalledWith({
        method: 'GET',
        url: 'https://example.com/bookapi/v1/iterative/bookCategory/programming/books/all',
        headers: {
          Host: 'example.com',
          Authorization: mAuthvalue,
        },
        body: undefined,
        json: true,
      });
    });

    it('should print an error when make request failed', async () => {
      const mAuthvalue = 'mocked auth value';
      jest.spyOn(BookService as any, 'getAuthValue').mockResolvedValueOnce(mAuthvalue);
      const logSpy = jest.spyOn(console, 'log');
      const mError = new Error('Internal server error');
      rp.mockRejectedValueOnce(mError);
      await BookService.getAllBookInCategory('programming');
      expect(rp).toBeCalledWith({
        method: 'GET',
        url: 'https://example.com/bookapi/v1/iterative/bookCategory/programming/books/all',
        headers: {
          Host: 'example.com',
          Authorization: mAuthvalue,
        },
        body: undefined,
        json: true,
      });
      expect(logSpy).toBeCalledWith(`Failed to get All Books in given category ${mError}`);
    });
  });
});

带有覆盖率报告的单元测试结果:

 PASS  src/stackoverflow/59315311/BookService.test.ts
  BookService
    #getAllBookInCategory
      ✓ should make request correctly (9ms)
      ✓ should print an error when make request failed (8ms)

  console.log node_modules/jest-mock/build/index.js:860
    Failed to get All Books in given category Error: Internal server error

----------------|----------|----------|----------|----------|-------------------|
File            |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------------|----------|----------|----------|----------|-------------------|
All files       |    73.91 |      100 |       60 |    72.22 |                   |
 BookService.ts |    73.91 |      100 |       60 |    72.22 |    21,28,30,32,52 |
----------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        5.662s, estimated 13s

您可以deleteBookInCategory以相同的方式测试方法。

源代码:https ://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/59315311


推荐阅读