Издевательство над бессерверным-mysql с использованием sinon

#node.js #sinon #serverless

#node.js #sinon #Бессерверный

Вопрос:

Я пытаюсь протестировать функцию AWS lambda (node.js ) создан с использованием AWS SAM. Моя функция использует модуль npm serverless-mysql для подключения к Aurora. Ниже приведены соответствующие части моей лямбда-функции:

 const connection = require('serverless-mysql')({
    config: {
        host     : process.env.DB_HOST,
        user     : process.env.DB_USER,
        password : process.env.DB_PASSWORD
    }
});

exports.lambdaHandler = async (event, context) => {
    try {
        const name = event.pathParameters.name;
        const rows = await connection.query('SELECT * FROM users WHERE name = ?', [name]);
        await connection.end()

        const user = rows[0];
        return {
            'statusCode': 200,
            'body': JSON.stringify({
                firstName: user.first_name,
                lastName: user.last_name,
                bk: user.bk,
                team: user.current_team
            })
        }

    } catch (err) {
        console.log(err);
        return err;
    }
};
  

Я пытаюсь протестировать это, издеваясь над serverless-mysql зависимостью, но в настоящее время я не могу этого сделать. Мой тест выглядит следующим образом:

 const app = require('../../app.js');
const chai = require('chai');
const sinon = require('sinon');
const expect = chai.expect;
const event = {
    pathParameters: {
        name: 'johndoe'
    }
}
var context;

var successConnectionObject = {
    connect: function() {
        return Promise.resolve();
    },
    query: function(sqlQuery, params) {
        return Promise.resolve('');
    },
    end: function() {} 
}

var mysql = require('serverless-mysql');
var stub = sinon.stub(mysql, 'connect').returns(successConnectionObject);

describe('Tests', function () {
    it('verifies successful response', async () => {
        const result = await app.lambdaHandler(event, context);

        expect(result).to.be.an('object');
        expect(result.statusCode).to.equal(200);
        mock.verify();

        mock.restore();
    });
});
  

Однако это возвращает следующую ошибку:

 TypeError: Cannot stub non-existent own property connect
  

Я полагаю, это потому, что mysql не создан экземпляр. Итак, я заменил строку var mysql = require('serverless-mysql'); на:

 var mysql = require('serverless-mysql')();
  

К сожалению, это приводит к следующей ошибке:

 AssertionError: expected [Error: Error: self signed certificate in certificate chain] to be an object
  

Похоже, вызывается connect() метод реального serverless-mysql модуля.

Как я могу правильно издеваться serverless-mysql с использованием sinon?

Ответ №1:

require('serverless-mysql') возвращает функцию, которая возвращает разное значение при каждом ее вызове, поэтому изменение свойств в результате одного вызова не повлияет на возвращаемое значение при другом вызове.

Это означает, что вы должны издеваться над самой функцией, что означает издевательство над всем модулем.

sinon не предоставляет способа издеваться над всем модулем, поэтому вам придется использовать что-то другое для этой части.

Вот рабочий тест, использующий proxyquire для издевательства над serverless-mysql модулем:

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

const event = {
  pathParameters: {
    name: 'johndoe'
  }
}
var context;

var successConnectionObject = {
  connect: function () {
    return Promise.resolve();
  },
  query: function (sqlQuery, params) {
    return Promise.resolve([{
      first_name: 'first',
      last_name: 'last',
      bk: 'bk',
      current_team: 'team'
    }]);
  },
  end: function () { }
}

const stub = sinon.stub().returns(successConnectionObject);
const app = proxyquire('../../app.js', { 'serverless-mysql': stub });

describe('Tests', function () {
  it('verifies successful response', async () => {
    const result = await app.lambdaHandler(event, context);

    expect(result).to.be.an('object');  // Success!
    expect(result.statusCode).to.equal(200);  // Success!

    sinon.assert.calledWithExactly(stub, {
      config: {
        host: process.env.DB_HOST,
        user: process.env.DB_USER,
        password: process.env.DB_PASSWORD
      }
    });  // Success!
  });
});
  

Комментарии:

1. Работает как шарм. И теперь я даже понял логику, стоящую за этим. Большое спасибо!

2. Добро пожаловать, рад слышать, что это было полезно! @dirkk