Макет конструктора зависимостей Jest

Я новичок в Jest. Я сумел издеваться над своими вещами, но, похоже, застрял в издевательстве над модулем. В частности, конструкторы.

usage.js

const AWS = require("aws-sdk")
cw = new AWS.CloudWatch({apiVersion: "2010-08-01"})
...
function myMetrics(params) { 
  cw.putMetricData(params, function(err, data){})
}

Я бы хотел сделать что-то подобное в тестах.

const AWS = jest.mock("aws-sdk")
class FakeMetrics {
  constructor() {}
  putMetricData(foo,callback) {
    callback(null, "yay!")
  }
}

AWS.CloudWatch = jest.fn( (props) => new FakeMetrics())

Однако, когда я использую его в usage.js cw - это mockConstructor не FakeMetrics

Я понимаю, что мой подход может быть "меньше, чем идиоматический", поэтому я был бы готов к любым указателям.

Это минимальный пример https://github.com/ollyjshaw/jest_constructor_so

npm install -g jest

jest

Ответ 1

Проблема в том, как издевается модуль. Поскольку эталонное состояние,

Извлекает модуль с автомодельной версией, когда это требуется. <...> Возвращает объект jest для цепочки.

AWS - это не объект модуля, а объект jest, а присвоение AWS.CloudFormation ничего не повлияет.

Кроме того, это CloudWatch в одном месте и CloudFormation в другом.

Рамки тестирования не требуют повторного использования макетных функций, они уже существуют. Это должно быть что-то вроде:

const AWS = require("aws-sdk");
const fakePutMetricData = jest.fn()
const FakeCloudWatch = jest.fn(() => ({
    putMetricData: fakePutMetricData
}));                        
AWS.CloudWatch = FakeCloudWatch;

И утверждал:

expect(fakePutMetricData).toHaveBeenCalledTimes(1);

Ответ 2

Над ответом работает. Однако после некоторого времени работы с jest я бы просто использовал функциональность mockImplementation, которая полезна для конструкторов- насмешников.

Ниже приведен пример кода:

import * as AWS from 'aws-sdk';

jest.mock('aws-sdk', ()=> {
    return {
        CloudWatch : jest.fn().mockImplementation(() => { return {} })
    }
});

test('AWS.CloudWatch is callled', () => {
    new AWS.CloudWatch();
    expect(AWS.CloudWatch).toHaveBeenCalledTimes(1);
});

Обратите внимание, что в этом примере новый CloudWatch() просто возвращает пустой объект.