Jest spyOn 没有检测到我的函数调用

Jest spyOn is not detecting my function call

我正在为基于数据库中的内容在网站上创建产品的流程编写单元测试。我知道这个过程是有效的,但作为最佳实践,我在下面添加了单元测试:

  describe('Creations Endpoints', () => {
    it('should create new product in Woo', async () => {
      await cronHelper.getNewProductsAndUploadToWoo();
      expect(getItemSkusWithWebContentSpy).toHaveBeenCalledTimes(1);
      expect(getAllProductsSpy).toHaveBeenCalledTimes(1);
      expect(getItemLocationDetailSpy).toHaveBeenCalledTimes(1);
      expect(getItemMasterSpy).toHaveBeenCalledTimes(1);
      expect(getItemWebContentBySkuSpy).toHaveBeenCalledTimes(1);
      expect(createProductSpy).toHaveBeenCalledTimes(1);
    });
  });

以下是间谍的设置:

beforeEach(async () => {
  getItemSkusWithWebContentSpy = jest
    .spyOn(opSuiteFunctions, 'getItemSkusWithWebContent')
    .mockImplementation(() => Promise.resolve(opsuiteData.getItemSkusWithWebContentData));
  getAllProductsSpy = jest.spyOn(wooFunctions, 'getAllProducts').mockImplementation(() => Promise.resolve(wooData.getAllProductsData.data));
  getItemLocationDetailSpy = jest
    .spyOn(opSuiteFunctions, 'getItemLocationDetail')
    .mockImplementation(() => Promise.resolve(opsuiteData.GetItemLocationDetailTransformed));
  getItemMasterSpy = jest.spyOn(opSuiteFunctions, 'getItemMaster').mockImplementation(() => Promise.resolve(opsuiteData.getItemMaster));
  getItemWebContentBySkuSpy = jest
    .spyOn(opSuiteFunctions, 'getItemWebContentBySku')
    .mockImplementation(() => Promise.resolve(opsuiteData.getItemWebContentBySku));
  createProductSpy = jest.spyOn(wooFunctions, 'createProduct').mockImplementation(() => Promise.resolve({ status: 201, headers: 'abc', data: 'tings' }));
  editProductSpy = jest.spyOn(wooFunctions, 'editProduct').mockImplementation(() => Promise.resolve({ status: 201, headers: 'def', data: 'stuff' }));
});

afterEach(() => {
  [getItemSkusWithWebContentSpy, getAllProductsSpy, getItemLocationDetailSpy, getItemMasterSpy, createProductSpy].forEach((mock) => {
    if (mock) mock.mockRestore();
  });
});

这些设置为 return 数据对象以模拟各种 API 调用。当我 运行 测试时,我看到日志输出表明所有函数都已被正确调用。然而,测试结果并没有反映出这一点:

  ● Cron Tests › Creations Endpoints › should create new product in Woo

    expect(jest.fn()).toHaveBeenCalledTimes(expected)

    Expected number of calls: 1
    Received number of calls: 0

      64 |       expect(getItemWebContentBySkuSpy).toHaveBeenCalledTimes(1);
    > 65 |       expect(createProductSpy).toHaveBeenCalledTimes(1);
         |                                ^
      66 |     });

      at Object.<anonymous> (tests/cronHelper.test.js:65:32)

正如我所说,我正在记录各个步骤,我可以看到调用了 createProductSpy 并且测试数据是 returned,如上面的 Spy 中所定义。

这是我要测试的实际代码的 createProduct 部分:

      // GetItemLocationDetail
      let getItemLocationDetailPromise = new Promise((resolve, reject) => {
        opSuiteFunctions
          .getItemLocationDetail(sku)
          .then((itemLocationDetail) => {
            resolve(itemLocationDetail);
          })
          .catch((err) => {
            reject(err);
          });
      }).catch((err) => console.error(err));

      // GetItemMaster
      let getItemMasterPromise = new Promise((resolve, reject) => {
        opSuiteFunctions
          .getItemMaster(sku)
          .then((item) => {
            resolve(item);
          })
          .catch((err) => {
            reject(err);
          });
      }).catch((err) => console.error(err));

      // GetItemWebContentBySku
      let getItemWebContentBySku = new Promise((resolve, reject) => {
        opSuiteFunctions
          .getItemWebContentBySku(sku)
          .then((itemWebContentBySku) => {
            resolve(itemWebContentBySku);
          })
          .catch((err) => {
            reject(err);
          });
      });

      const { itemLocationDetail, itemMaster, itemWebContent } = await Promise.all([getItemLocationDetailPromise, getItemMasterPromise, getItemWebContentBySku])
        .then(([itemLocationDetail, itemMaster, itemWebContent]) => {
          return { itemLocationDetail, itemMaster, itemWebContent };
        })
        .catch((err) => {
          throw { message: `Failed to resolve promise: `, details: err };
        });

      // Create the product object
      let product = {
       ...
      };

      // Create the product in WooCommerce
      const createResult = await wooFunctions
        .createProduct(product)
        .then((res) => {
          return res;
        })
        .catch((err) => {
          throw { message: `Failed to create product with sku: ${sku}`, details: err };
        });

      if (createResult.status !== 201) {
        throw { message: `Failed to create product with sku: ${sku}`, details: `createProduct returned with response ${createResult}` };
      }

      console.info(`Successfully created product with sku: ${sku}`);
    });

我通过将 expect(createProductSpy).toHaveBeenCalledTimes(1); 包装在 setTimeout 中解决了这个问题。