node.js - 如何使用 jest 在课堂上测试功能
问题描述
我无法使用 jest 进行单元测试
我正在尝试测试一个特定的函数,该函数正在调用或期待其他函数的结果,但我不确定它为什么不起作用。我对单元测试很陌生,真的不知道如何让它工作。目前这是我尝试过的
export class OrganizationService {
constructor() {
this.OrganizationRepo = new OrganizationRepository()
}
async getOrganizations(req) {
if (req.permission !== 'internal' && req.isAuthInternal === false) {
throw new Error('Unauthenticated')
}
const opt = { deleted: true }
return this.OrganizationRepo.listAll(opt)
}
}
这是我扩展 MongoDbRepo 的 OrganizationRepository
import { MongoDbRepo } from './mongodb_repository'
export class OrganizationRepository extends MongoDbRepo {
constructor(collection = 'organizations') {
super(collection)
}
}
这是 MongoDbRepo
const mongoClient = require('../config/mongo_db_connection')
const mongoDb = require('mongodb')
export class MongoDbRepo {
constructor(collectionName) {
this.collection = mongoClient.get().collection(collectionName)
}
listAll(opt) {
return new Promise((resolve, reject) => {
this.collection.find(opt).toArray((err, data) => {
if (err) {
reject(err)
}
resolve(data)
})
})
}
}
这是我所做的测试
import { OrganizationService } from '../../../src/services/organization_service'
describe('getOrganizations', () => {
it('should return the list of organizations', () => {
// const OrgRepo = new OrganizationRepository()
const orgService = new OrganizationService()
const OrgRepo = jest.fn().mockReturnValue("[{_id: '123', name: 'testname'}, {_id: '456, name: 'testname2'}]")
// orgService.getOrganizations = jest.fn().mockReturnValue('')
const result = orgService.getOrganizations()
expect(result).toBe(OrgRepo)
})
})
解决方案
我在您的测试方式中发现了两个问题:
1.
expect
您正在尝试测试一个异步方法,并且在您的测试中,您不会在您的语句之前等待此方法完成。
一个好的测试结构应该是:
it('should test your method', (done) => {
const orgService = new OrganizationService();
const OrgRepo = jest.fn().mockReturnValue("[{_id: '123', name: 'testname'}, {_id: '456, name: 'testname2'}]")
orgService.getOrganizations()
.then((result) => {
expect(result).toEqual(OrgRepo); // I recommend using "toEqual" when comparing arrays
done();
});
})
不要忘记将done
其作为测试参数!
您可以在Jest 官方文档中找到更多关于测试异步函数的信息。
2.
为了正确测试您的方法,您希望将其与外部依赖项隔离开来。OrganizationRepo.listAll()
这里调用了实际的方法。您想模拟此方法,例如使用间谍,以便您控制其结果并仅测试该getOrganizations
方法。看起来像这样:
it('should test your method', (done) => {
const req = {
// Whatever structure it needs to be sure that the error in your method is not thrown
};
const orgService = new OrganizationService();
const orgRepoMock = spyOn(orgService['OrganizationRepo'], 'listAll')
.and.returnValue(Promise.resolve("[{_id: '123', name: 'testname'}, {_id: '456, name: 'testname2'}]"));
const OrgRepo = jest.fn().mockReturnValue("[{_id: '123', name: 'testname'}, {_id: '456, name: 'testname2'}]");
orgService.getOrganizations(req)
.then((result) => {
expect(result).toEqual(OrgRepo); // I recommend using "toEqual" when comparing arrays
expect(orgRepoMock).toHaveBeenCalled(); // For good measure
done();
});
})
这样,我们确保您的方法是孤立的,并且其结果不能被外部方法改变。
对于这种特定的方法,我还建议您根据方法的输入来测试抛出的错误。
推荐阅读
- sql-server - 在 SQL Server 2019 中安装 PolyBase 时出错
- amazon-web-services - AWS SageMaker EndPoint 返回 415
- java - Hibernate Javax Persistence:对象不是声明类的实例
- php - Slim 4 - 基本路径作为查询参数
- c++ - std::set 背后的直觉是什么
::find() 函数使用 '<' 运算符而不是 '==' 运算符? - http - 如何在 vue-cli 中设置 HTTP 标头?
- laravel - Laravel 6.0 本地服务器
- web-deployment - 是否有任何在线编译器 API,如果我输入源代码,它会在编译时返回结果(或任何错误)?
- javascript - Vue.js Typescript 组件不会更新异步回调的视图
- mysql - 在 MySQL 中实现 where 条件 varchar 字段