Thi*_*obo 4 javascript unit-testing jest react-redux
我的问题是我试图对某个功能进行单元测试,但无法弄清楚如何测试其中的一部分。
这是一个react / redux操作,它执行以下操作:
1)使用图像网址检索json数据
2)将图像加载到Image实例中,并将其大小分派给reducer(使用Image.onload加载图像时异步)
3)派遣完成到减速机的提取
图片加载是异步发生的,因此当我尝试进行单元测试时,它不会被调用。而且,我不能只是模拟一下,因为图像实例是在函数内创建的。
这是我要测试的代码(删除了一些检查,分支逻辑和内容):
export function fetchInsuranceCardPhoto() {
return dispatch => {
dispatch(requestingInsuranceCardPhoto());
return fetch(`${api}`,
{
headers: {},
credentials: 'same-origin',
method: 'GET',
})
.then(response => {
switch (response.status) {
case 200:
return response.json()
.then(json => {
dispatch(receivedInsuranceCardPhoto(json));
})
}
});
};
}
function receivedInsuranceCardPhoto(json) {
return dispatch => {
const insuranceCardFrontImg = json.insuranceCardData.url_front;
const insuranceCardBackImg = json.insuranceCardData.url_back;
if (insuranceCardFrontImg) {
dispatch(storeImageSize(insuranceCardFrontImg, 'insuranceCardFront'));
}
return dispatch(receivedInsuranceCardPhotoSuccess(json));
};
}
function receivedInsuranceCardPhotoSuccess(json) {
const insuranceCardFrontImg = json.insuranceCardData.url_front;
const insuranceCardBackImg = json.insuranceCardData.url_back;
const insuranceCardId = json.insuranceCardData.id;
return {
type: RECEIVED_INSURANCE_CARD_PHOTO,
insuranceCardFrontImg,
insuranceCardBackImg,
insuranceCardId,
};
}
function storeImageSize(imgSrc, side) {
return dispatch => {
const img = new Image();
img.src = imgSrc;
img.onload = () => {
return dispatch({
type: STORE_CARD_IMAGE_SIZE,
side,
width: img.naturalWidth,
height: img.naturalHeight,
});
};
};
}
Run Code Online (Sandbox Code Playgroud)
注意在最后一个storeImageSize私有函数中,如何创建Image实例和分配给函数的image.onload。
现在这是我的测试:
it('triggers RECEIVED_INSURANCE_CARD_PHOTO when 200 returned without data', async () => {
givenAPICallSucceedsWithData();
await store.dispatch(fetchInsuranceCardPhoto());
expectActionsToHaveBeenTriggered(
REQUESTING_INSURANCE_CARD_PHOTO,
RECEIVED_INSURANCE_CARD_PHOTO,
STORE_CARD_IMAGE_SIZE,
);
});
Run Code Online (Sandbox Code Playgroud)
但是此测试将失败,因为该测试在image.onload调用回调之前完成。
如何强制image.onload调用回调,以便测试是否可以广播`STORE_CARD_IMAGE_SIZE操作?
经过一番调查,我发现了一个非常有趣的javascript函数,可以解决我的问题。
它是这样的:https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
这是我过去Object.defineProperty(...)解决问题的方式:
describe('fetchInsuranceCardPhoto', () => {
let imageOnload = null;
/** Override Image global to save onload setting here so that I can trigger it manually in my test */
function trackImageOnload() {
Object.defineProperty(Image.prototype, 'onload', {
get: function () {
return this._onload;
},
set: function (fn) {
imageOnload = fn;
this._onload = fn;
},
});
}
it('triggers RECEIVED_INSURANCE_CARD_PHOTO when 200 returned with data', async () => {
trackImageOnload();
givenAPICallSucceedsWithData();
await store.dispatch(fetchInsuranceCardPhoto());
imageOnload();
expectActionsToHaveBeenTriggered(
REQUESTING_INSURANCE_CARD_PHOTO,
RECEIVED_INSURANCE_CARD_PHOTO,
STORE_CARD_IMAGE_SIZE,
);
});
Run Code Online (Sandbox Code Playgroud)
我在这里所做的是使用define属性覆盖的任何实例的setter Image。设置器将继续正常进行获取或设置,但还将保存在单元测试范围内设置为变量的值(在这种情况下为函数)。之后,您可以运行在测试的验证步骤之前捕获的功能。
陷阱
-需要设置可配置-注意defineProperty与以下功能不同defineProperties
-这在实际代码中是不好的做法。-记得使用原型
希望这篇文章可以帮助有需要的开发者!
| 归档时间: |
|
| 查看次数: |
4157 次 |
| 最近记录: |