是否可以使用Jest来模拟在方法中使用的内部类对象

huangapple go评论59阅读模式
英文:

Is it possible to mock an internal class object used in a method using Jest

问题

这是您要翻译的代码部分:

import { ProductMetadata } from './product/metadata'
import { LookupService } from './service/lookup'
import { DataHandler } from './product-handlers/data-handler'

class ProductDatatHandler {

  async process(data: ProductMetadata, service: LookupService): Promise<void> {
    if (data.value) {
      try {
        const processor = await service.getProductHandlerForType(data.type)
        const dataHandler = new DataHandler(processor)
        await dataHandler.insert(data)
      } catch (error) {
        console.error('Failed to persist data ', error)
      }
    }
  }
}

export { ProductDatatHandler }

您尝试模拟的部分是这一行:困难在于它是在内部创建的。我不知道Jest是否有一种方法来模拟这一行。一切都运行正常,只是dataHandler未定义。

const dataHandler = new DataHandler(processor)

我尝试使用以下方法,但收到了TypeError DataHander is not a constructor错误:

jest.mock('./product-handlers/data-handler', () => (
  {
    __esModule: true,
    insert: jest.fn()
  }
))

还有一个相关的类的导入:

import {ProductProcessor } from './processor/product-processor'
   
class DataHandler {
   private productProcessor:ProductProcessor
   constructor(productProcessor: ProductProcessor){
    this.productProcessor = productProcessor
   }
   ...
}

请注意,我没有翻译您的问题部分,只提供了代码的翻译。如果您需要进一步的帮助或解释,请告诉我。

英文:

I have a class whose sole function is to process a data type called ProductMetadata. There is a lookup service that picks a handler depending on the ProductMetadata type that is passed to the method by a LookupService object. I am able mock all the other objects except the DataHander object that's created in the process method

Here is the code

import { ProductMetadata } from &#39;./product/metadata&#39;
import { LookupService } from &#39;./service/lookup&#39;
import { DataHandler } from &#39;./product-handlers/data-handler&#39;


class ProductDatatHandler {

  async process(data: ProductMetadata, service: LookupService): Promise&lt;void&gt; {
    if (data.value) {
      try {
        const processor = await service.getProductHandlerForType(data.type)
        const dataHandler = new DataHandler(processor)
        await dataHandler.insert(data)
      } catch (error) {
        console.error(&#39;Failed to persist data &#39;, error)
      }
    }
  }
}

export { ProductDatatHandler }

The portion I am unable to mock successfully is this line: The difficulty is that it is created internally. I don't know if Jest has a way to mock this line. Everything works except that the dataHandler is undefined.

const dataHandler = new DataHandler(processor)

How can I mock the DataHandler class?

I tried using this but I got a TypeError DataHander is not a constructor

jest.mock(&#39;./product-handlers/data-handler&#39;, () =&gt; (
  {
    __esModule: true,
    insert: jest.fn()
  }
))

```ts

    import {ProductProcessor } from &#39;./processor/product-processor&#39;
   
    class DataHandler {
       private productProcessor:ProductProcessor
       constructor(productProcessor: ProductProcessor){
        this.productProcessor = productProcessor
       }
       ...
    }

答案1

得分: 2

以下是您要翻译的内容:

"You didn't mock the ./product-handlers/data-handler module and DataHandler class correctly. Use jest.mock() to mock a module with an auto-mocked version.

"jest": "^26.6.3"

product-data-handler.js:

import { DataHandler } from './product-handlers/data-handler';

class ProductDatatHandler {

  async process(data, service) {
    if (data.value) {
      try {
        const processor = await service.getProductHandlerForType(data.type)
        const dataHandler = new DataHandler(processor)
        await dataHandler.insert(data)
      } catch (error) {
        console.error('Failed to persist data ', error)
      }
    }
  }
}

export { ProductDatatHandler }

product-handlers/data-handler.js

class DataHandler {
  insert(data) {
    return Promise.resolve('ok')
  }
}

export { DataHandler };

product-data-handler.test.js:

import { DataHandler } from './product-handlers/data-handler'
import { ProductDatatHandler } from './product-data-handler'

jest.mock('./product-handlers/data-handler');

describe('76429246', () => {
  test('should pass', async () => {
    const dataHandlerInstanceMock = {
      insert: jest.fn()
    }
    DataHandler.mockImplementation(() => dataHandlerInstanceMock);

    const lookUpServiceMock = {
      getProductHandlerForType: jest.fn()
    }
    const productDataHandler = new ProductDatatHandler();
    await productDataHandler.process({ type: 'a', value: 'b' }, lookUpServiceMock);
    expect(lookUpServiceMock.getProductHandlerForType).toHaveBeenCalledWith('a');
    expect(dataHandlerInstanceMock.insert).toHaveBeenCalledWith({ type: 'a', value: 'b' });
  });
});

Test result:

 PASS  stackoverflow/76429246/product-data-handler.test.js (18.035 s)
  76429246
    ✓ should pass (6 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        18.944 s, estimated 25 s

UPDATE:

You can handle the TS type using jest.mocked(source, options?)

const DataHandlerMock = jest.mocked(DataHandler);
// ...

DataHandlerMock.mockImplementation(() => dataHandlerInstanceMock);
英文:

You didn't mock the ./product-handlers/data-handler module and DataHandler class correctly. Use jest.mock() to mock a module with an auto-mocked version.

"jest": "^26.6.3"

product-data-handler.js:

import { DataHandler } from &#39;./product-handlers/data-handler&#39;

class ProductDatatHandler {

  async process(data, service) {
    if (data.value) {
      try {
        const processor = await service.getProductHandlerForType(data.type)
        const dataHandler = new DataHandler(processor)
        await dataHandler.insert(data)
      } catch (error) {
        console.error(&#39;Failed to persist data &#39;, error)
      }
    }
  }
}

export { ProductDatatHandler }

product-handlers/data-handler.js

class DataHandler {
  insert(data) {
    return Promise.resolve(&#39;ok&#39;)
  }
}

export { DataHandler };

product-data-handler.test.js:

import { DataHandler } from &#39;./product-handlers/data-handler&#39;
import { ProductDatatHandler } from &#39;./product-data-handler&#39;

jest.mock(&#39;./product-handlers/data-handler&#39;);

describe(&#39;76429246&#39;, () =&gt; {
  test(&#39;should pass&#39;, async () =&gt; {
    const dataHandlerInstanceMock = {
      insert: jest.fn()
    }
    DataHandler.mockImplementation(() =&gt; dataHandlerInstanceMock);

    const lookUpServiceMock = {
      getProductHandlerForType: jest.fn()
    }
    const productDataHandler = new ProductDatatHandler();
    await productDataHandler.process({ type: &#39;a&#39;, value: &#39;b&#39; }, lookUpServiceMock);
    expect(lookUpServiceMock.getProductHandlerForType).toHaveBeenCalledWith(&#39;a&#39;);
    expect(dataHandlerInstanceMock.insert).toHaveBeenCalledWith({ type: &#39;a&#39;, value: &#39;b&#39; });
  });
});

Test result:

 PASS  stackoverflow/76429246/product-data-handler.test.js (18.035 s)
  76429246
    ✓ should pass (6 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        18.944 s, estimated 25 s

UPDATE:

You can handle the TS type using jest.mocked(source, options?)

const DataHandlerMock = jest.mocked(DataHandler);
// ...

DataHandlerMock.mockImplementation(() =&gt; dataHandlerInstanceMock);

huangapple
  • 本文由 发表于 2023年6月8日 14:45:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/76429246.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定