问题
I have a file that exports some functions:
function getNow() {
console.log('real now');
return dayjs();
}
function groupProducts(productInfos, now) {
console.log('real group');
return productInfos.reduce((groups, productInfo) => {
const groupKey = dayjs(productInfo.saleStartDate) > now ? dayjs(productInfo.saleStartDate).format('YYYY-MM-DD') : dayjs(now).format('YYYY-MM-DD');
let group = groups[groupKey];
if (!group) {
group = [];
// eslint-disable-next-line no-param-reassign
groups[groupKey] = group;
}
group.push(productInfo.itemId);
return groups;
}, {});
}
async function fetchProducts(client, productInfos, now) {
const products = [];
const groups = groupProducts(productInfos, now);
for (const [date, ids] of Object.entries(productQueryGroups)) {
// eslint-disable-next-line no-await-in-loop
const productBatch = await fetchResources(
client.queryProducts,
{
articleIds: ids,
timestamp: date,
},
);
products.push(...productBatch);
}
return products;
}
module.exports = {
test: {
getNow,
groupProducts,
fetchProducts,
},
};
I run my tests with:
package.json script
"testw": "npx ../node_modules/.bin/jest --watch",
cli command:
npm run testw -- filename
In this test I exercise groupProducts
and mock getNow
. The real getNow
is never called and the test passes.
describe('groupProducts', () => {
it('groups productInfo ids into today or future date groups', () => {
// Arrange
const nowSpy = jest.spyOn(test, 'getNow').mockReturnValue(dayjs('2001-02-03T04:05:06.007Z'));
const expectedMap = {
'2001-02-03': ['Art-Past', 'Art-Today'],
'2002-12-31': ['Art-Future-1', 'Art-Future-2'],
'2003-12-31': ['Art-Other-Future'],
};
const productInfos = [{
itemId: 'Art-Past',
saleStartDate: '1999-01-01',
}, {
itemId: 'Art-Today',
saleStartDate: '2001-02-03',
}, {
itemId: 'Art-Future-1',
saleStartDate: '2002-12-31',
}, {
itemId: 'Art-Future-2',
saleStartDate: '2002-12-31',
}, {
itemId: 'Art-Other-Future',
saleStartDate: '2003-12-31',
}];
// Assert
const dateToIds = test.groupProductInfosByTodayOrFutureDate(productInfos, test.getNow());
// Expect
expect(dateToIds).toEqual(expectedMap);
// Restore
nowSpy.mockRestore();
});
});
In this test I exercise fetchProducts
and mock groupProducts
. The real groupProducts
is called and the causes the test to fail.
describe('fetchProducts', () => {
it.only('calls fetchResources with the timestamp and date for every product query group', async () => {
// Arrange
const productQueryGroups = {
[test.PRICE_GROUPS.CURRENT]: ['Art-Past', 'Art-Today'],
[test.PRICE_GROUPS.FUTURE]: ['Art-Future-1', 'Art-Future-2', 'Art-Other-Future'],
};
const groupProductsSpy = jest.spyOn(test, 'groupProducts').mockReturnValue( productQueryGroups);
const fetchResourcesSpy = jest.spyOn(test, 'fetchResources').mockResolvedValue([]);
// Act
await test.fetchProducts();
// Expect
expect(test.fetchResources).toHaveBeenCalledWith(expect.anything(), expect.objectContaining({ articleIds: [productQueryGroups[test.PRICE_GROUPS.CURRENT]], timestamp: test.PRICE_GROUPS.CURRENT }));
// Restore
groupProductsSpy.mockRestore();
fetchResourcesSpy.mockRestore();
});
});
Error message
98 | function groupProducts(productInfos, now) {
> 99 | return productInfos.reduce((groups, productInfo) => {
| ^
100 | const groupKey = dayjs(productInfo.saleStartDate) > now ? dayjs(productInfo.saleStartDate).format('YYYY-MM-DD') : dayjs(now).format('YYYY-MM-DD');
101 |
102 | let group = groups[groupKey];
Why is the real groupProducts
called? To me it looks completely analogous to the previous example.
来源:https://stackoverflow.com/questions/65306809/i-am-mocking-two-functions-exactly-the-same-way-in-one-case-the-mock-value-is-r