gpt4 book ai didi

javascript - 如何在 redux 操作(或操作中分配的其他回调)的上下文中使用 jest 测试 `image.onload`

转载 作者:搜寻专家 更新时间:2023-11-01 05:28:06 24 4
gpt4 key购买 nike

我的问题是我正在尝试对一个函数进行单元测试,但不知道如何测试它的一部分。

这是一个执行以下操作的 react/redux 操作:

1) 检索带有图像 url 的 json 数据

2) 将图像加载到 Image 实例中并将其大小分派(dispatch)给 reducer(当使用 Image.onload 加载图像时异步)

3) 将抓取完成发送给reducer

图像加载是异步发生的,所以当我尝试对它进行单元测试时,它不会被调用。此外,我不能只是模拟事情,因为图像实例是在函数内创建的...

这是我想测试的代码(删除了一些检查、分支逻辑等):

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,
});
};
};
}

请注意在最后一个 storeImageSize 私有(private)函数中,如何创建一个 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,
);
});

这个测试虽然会失败,因为测试在调用 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,
);
});

我在这里所做的是使用 define 属性来覆盖 Image 的任何实例的 setter 。 setter 将像往常一样继续获取或设置,但也会保存设置为单元测试范围内变量的值(在本例中为函数)。之后,您只需运行在测试的验证步骤之前捕获的函数即可。

陷阱- 需要设置configurable- 请注意 defineProperty 是一个不同于 defineProperties 的函数- 这在实际代码中是不好的做法。- 记得使用原型(prototype)

希望这篇文章可以帮助有需要的开发者!

关于javascript - 如何在 redux 操作(或操作中分配的其他回调)的上下文中使用 jest 测试 `image.onload`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47273782/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com