I am mocking two functions exactly the same way. In one case the mock value is returned and in another case the real function is called. Why?

醉酒当歌 提交于 2021-01-29 08:14:15

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!