我正在努力模拟以下功能。我需要模拟两种方法:getAllBookInCategory
,deleteBookInCategory
公共方法调用私有方法,我假设我不必测试私有方法,只需调用公共方法并验证是否调用私有方法。正确吗?
公共方法:getAllBookInCategory
,deleteBookInCategory
私有方法: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
};
}
}
答案 0 :(得分:0)
这是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