我现在在一家公司工作,那里有很多非常专业的库-带有内部状态和回调地狱之类的库,这使得该死的几乎无法进行单元测试。
该公司还要求90%的单元测试覆盖率。好玩好玩。
让我感到“疯狂”的一件事就是这种疯狂:
为了进行API调用,您需要一个JWT令牌。为了获得JWT令牌,您需要从私有NPM存储库中导入一个名为“ jwt-client”的库
“ jwt-client”导出函数“ JWTJourney”和“ setJWTParams”。
setJWTParams采用一个对象作为授予类型和范围,该对象设置内部状态以与JWTJourney一起使用。
(因此,您不仅具有面向对象的设计,而且不是面向类的OO设计,而是构造成全局变量或闭包变量的独立函数,它们使我不得不承担的责任)。>
JWTJourney采用单个参数-Redux调度功能。 (为什么要这样做?因为假设您使用的是“ dynamic-redux”私有库,并且已经引入了reducer和action类型,尽管它不允许您运行中间件,例如“ redux-saga ”或“记录器”)
JWTJourney(dispatch)返回一个send方法,该方法接受一个回调,其中第一个参数包含一个带有名为token的属性的对象。
因此,此方法的设计方式是说您需要进行api调用。您将这样编写代码。
const data = await JWTJourney(dispatch).send(({token}) => myApiCall(token, params));
我对自己想:我们已经异步等待,.send返回了一个承诺,所以为什么不呢?
// getToken.js
const getToken = async (dispatch) => await JWTJourney(dispatch).send(({token}) => token)
// logic.js
import getToken from './getToken'
const token = await getToken();
const data = myApiCall(token);
因此,我认为您不必一直重写JWT旅程,等等。
我以为它很聪明。但是我不知道(并且因为没有文档而无法知道)是JWTJourney.send的代码类似于:
send: (callback) => {
try {
callback({token: this.token})
catch (err) {
if(err.type === 'OAuthException'){ // if unauthorised
if(!this.token){
this.getNewToken().then(() => callback({token: this.token});
} else {
this.renewToken(this.token).then(() => callback ({token: this.token);
}
}
换句话说,除非回调传递到send方法中执行失败 ,否则令牌不会更新。
这意味着...您将如何处理这样的情况:
const test1 = await JWTJourney(dispatch).send(({token}) => test1Api(token));
const test2 = await JWTJourney(dispatch).send(({token}) => test2Api(token));
expect(test1).not.toEqual(test2);
如果模拟“发送”,则无法以任何方式区分test1中发送的回调和test2中发送的回调。这意味着即使您将.send()
嘲笑为jest.fn(() => Promise.resolve(mockData))
之类的东西,您也会得到test1 === mockData && test2 === mockData;
无论我做什么,似乎都无法找到一种方法来对此进行单元测试(同样,根据公司政策,我需要90%的测试覆盖率。)
我正在寻找两件事。首先是验证-我不是疯狂,对吗? 这就是我想的那样,对吗?
第二-以这种方式进行操作的理由之一是,根据我的团队负责人,您“永远不要在Redux商店周围悬挂过期的令牌”。另外,您不能依赖时钟,因为最终用户的时钟可能有误。如果您必须使用相同的功能重写某些内容:令牌到期后应该刷新-您将如何编写?因为我有种有趣的感觉,所以我将不得不重写它。