Как смоделировать / передать вспомогательную утилиту Nodejs, которая выполняет в ней функции, используя mocha-chai-sinon - PullRequest
0 голосов
/ 16 января 2019

Допустим, у меня есть файл, как показано ниже:

ЦСИ / blah.js

var Foo = require("../../something/foo.js");

var goo = new Foo({
  host: argv.host.toString(),
  port: parseInt(argv.port)
});
goo.order("service_name");
goo.do("invalidPhone", function(req, done) {
  goo.talk('newFunc', 'newAct', req.data, function(newActErr, newActResponse){
       done(newActResponse)
  })
});

exports.goo = goo;

Где "something / foo.js" - это вспомогательный проект утилиты, который выполняет различные функции. Допустим, goo.order где-то регистрирует имя_службы, а goo.do фактически выполняет некоторую работу, используя invalidPhone в качестве имени функции.

В этом случае некоторые другие сервисные вызовы функции invalidPhone с некоторым параметром req. Когда вызывается функция invalidPhone, функция должна вывести «Здесь!» вместе с тем, что приходит в req.data.

Могу ли я написать пример модульного теста для функции invalidPhone? Я предполагаю, что для достижения этого мне нужно как-то издеваться goo.do(), но как мне это сделать?

Я попытался написать тестовый пример, как показано ниже:

var eventService = require("../src/blah");
var base = eventService.goo;
var sinon = require("sinon");

describe("Goo Blah service", function(done) {
  beforeEach(function() {
    this.consoleSpy = sinon.spy(console, "log");
  });

  afterEach(function() {
    this.consoleSpy.restore();
  });

  it("Response should be logged", function() {
    goo.action("invalidPhone", "a123456789");
    this.consoleSpy.called.should.be.true;
  });
});

Но вышеприведенное, похоже, не работает.

РЕДАКТИРОВАТЬ 1: Что делать, если мой код выглядит следующим образом, и у меня есть новая функция goo.talk для макетирования / заглушки и возврата некоторых значений в newActErr и newActResp? Значения newFunc и newAct могут изменяться. Как мне тогда это сделать?

var Foo = require("../../something/foo.js");

var goo = new Foo({
  host: argv.host.toString(),
  port: parseInt(argv.port)
});
goo.order("service_name");
goo.do("invalidPhone", function(req, done) {
  goo.talk('newFunc', 'newAct', req.data, function(newActErr, newActResponse){
       if(newActResponse.status){
          done(null, newActResponse)
       } else {
          done('error', null)
       }

  })
});

exports.goo = goo;

Исходя из подсказки / помощи, предоставленной deerawan, я попробовал следующее:

talkStub = sinon.stub().withArgs('newFunc', 'newAct', {data: "name"}).returns({"status":"online"})

1 Ответ

0 голосов
/ 26 января 2019

Ваш тест не может работать, потому что вы издеваетесь / шпион console.log после загрузки исходного файла blah в начале файла

var eventService = require("../src/blah");

Кроме того, лучше также смоделировать класс Foo, чтобы тест стал изолированным.

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

Посмотрите на решение ниже:

const chai = require('chai');
const proxyquire = require('proxyquire');
const sinon = require('sinon');

// need to specify this so Foo constructor can be initialized
process.argv.host = 'http';
process.argv.port = '333';

describe("Goo Blah service", function() {
  let consoleSpy;
  let orderStub;
  let doStub;

  beforeEach(function() {
    orderStub = sinon.stub();
    doStub = sinon.stub().yields({ data: 'mine' });

    // this our mock for Foo class
    function MockFoo() {
      return {
        order: orderStub,
        do: doStub,
      }  
    }

    consoleSpy = sinon.spy(console, 'log');

    // require the source file and mock `foo`
    proxyquire('../src/blah', { '../../something/foo.js': MockFoo } );
  });

  afterEach(function() {
    sinon.restore();
  });

  it("Response should be logged", function() {
    sinon.assert.calledWith(orderStub, 'service_name');
    sinon.assert.calledWith(doStub, 'invalidPhone');

    sinon.assert.called(consoleSpy);
    sinon.assert.calledWith(consoleSpy, 'Here!', 'mine');
  });
});

Надеюсь, это поможет

...