【问题标题】:Mock a method of a service called by the tested one when using Jest在使用 Jest 时模拟被测试者调用的服务方法
【发布时间】:2017-05-02 15:29:54
【问题描述】:

我正在尝试模拟从测试中导出为模块的方法服务。 这是我用“sinon”做的事情,但我想尽可能多地使用jest。

这是一个经典的测试,我有一个“身份验证”服务和一个“邮件”服务。

“身份验证”服务可以注册新用户,每次新注册后,它都会要求邮件服务向新用户发送一封“欢迎邮件”。

所以测试我的身份验证服务的注册方法,我想断言(并模拟)邮件服务的“发送”方法。

如何做到这一点?这是我尝试过的,但它调用了原始的 mailer.send 方法:

// authentication.js

const mailer = require('./mailer');

class authentication {
  register() { // The method i am trying to test
    // ...

    mailer.send();
  }
}

const authentication = new Authentication();

module.exports = authentication;


// mailer.js

class Mailer {
  send() { // The method i am trying to mock
    // ...
  }
}

const mailer = new Mailer();

module.exports = mailer;


// authentication.test.js

const authentication = require('../../services/authentication');

describe('Service Authentication', () => {
  describe('register', () => {
    test('should send a welcome email', done => {
      co(function* () {
        try {
          jest.mock('../../services/mailer');
          const mailer = require('../../services/mailer');
          mailer.send = jest.fn( () => { // I would like this mock to be called in authentication.register()
            console.log('SEND MOCK CALLED !');
            return Promise.resolve();
          });

          yield authentication.register(knownUser);

          // expect();

          done();
        } catch(e) {
          done(e);
        }
      });
    });
  });
});

【问题讨论】:

    标签: javascript jestjs


    【解决方案1】:

    首先,您必须使用 spy 模拟 mailer 模块,以便稍后进行设置。如果您想开玩笑地了解在测试中使用 Promise,请查看 docs 了解两种方法。

    const authentication = require('../../services/authentication');
    const mailer = require('../../services/mailer');
    jest.mock('../../services/mailer', () => ({send: jest.fn()})); 
    
    describe('Service Authentication', () => {
      describe('register', () => {
        test('should send a welcome email', async() => {
              const p = Promise.resolve()
              mailer.send.mockImplementation(() =>  p) 
              authentication.register(knownUser);
              await p
              expect(mailer.send).toHaveBeenCalled;
            }
          });
        });
      });
    });
    

    【讨论】:

    • 感谢您的回答,我只想在验证答案之前了解一件事,您知道为什么只有在我们需要并在 test() 之外调用 jest.mock 时它才有效吗?例如,为什么我不能在 beforeEach 中这样做(我测试过,它不起作用,我不知道为什么)。谢谢!
    • 究竟什么不能移到beforEach
    • beforeEach( () => { const mailer = require('../../services/mailer'); jest.mock('../../services/mailer', ( ) => ({send: jest.fn()})); mailer.send.mockImplementation( () => Promise.resolve() ) });
    • 啊,关键是你需要在你的测试中引用promise。要么将 em 用于async/await,要么从测试中返回 em。因此,如果您存储对承诺的引用并在测试中使用它,就像我的回答一样,它应该与 beforeEach 一起使用。
    • 它与promise无关,而是与mock函数本身有关,如果我将此代码放在beforeEach()甚至test()的顶部,则会调用原始的mailer.send函数而不是模拟。看起来我们必须在描述之外要求和 jest.mock 邮件程序,但我不明白为什么它的行为不同。
    猜你喜欢
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-30
    • 1970-01-01
    • 2021-11-16
    • 2021-03-09
    相关资源
    最近更新 更多