Как я могу написать правильный тест с Mocha для функции с asyn c await и попробовать catch? - PullRequest
0 голосов
/ 06 января 2020

У меня есть функция, где я беру всех авторов из Mongodb. Я новичок в тестировании, я потратил часы сам и в Интернете, пытаясь придумать хорошие тестовые примеры, но не могу понять, как я могу правильно проверить функциональность здесь. errorHandler - это просто класс для обработки ошибок, а функция обтекания просто оборачивает ошибку описанием.

    const { MongoClient } = require('mongodb');
    const credentials = require('../database-credentials');
    const mongoClient = new MongoClient(credentials.URI,{useUnifiedTopology: true });
    mongoClient.connect();
    const mongodb = mongoClient.db();

    async getAllAuthors (cb) {
        try {
            const result = await mongodb.collection('authors').find({}).toArray();
            return cb(null, result);
        } catch (error) {
            return cb(errorHandler.wrap(error, 'while fetching all authors in the book'));
        }
    }

1 Ответ

0 голосов
/ 07 января 2020

Вам нужно использовать библиотеку-заглушку, например sinon.js, чтобы заглушить метод побочных эффектов. Для вашего случая метод побочных эффектов mongodb.collection().find().toArray(). Каждый тестовый случай должен проверять только один сценарий.

Вот решение для модульного теста:

index.ts:

const errorHandler = {
  wrap(error, message) {
    console.log(message);
    return error;
  },
};

export default class SomeClass {
  mongodb;
  constructor(mongodb) {
    this.mongodb = mongodb;
  }
  async getAllAuthors(cb) {
    try {
      const result = await this.mongodb
        .collection('authors')
        .find({})
        .toArray();
      return cb(null, result);
    } catch (error) {
      return cb(errorHandler.wrap(error, 'while fetching all authors in the book'));
    }
  }
}

index.test.ts:

import SomeClass from './';
import sinon from 'sinon';

describe('59609593', () => {
  let instance;
  const mongodbStub = {
    collection: sinon.stub().returnsThis(),
    find: sinon.stub().returnsThis(),
    toArray: sinon.stub(),
  };
  beforeEach(() => {
    instance = new SomeClass(mongodbStub);
  });
  afterEach(() => {
    sinon.restore();
  });
  it('should find authors correctly', async () => {
    const callback = sinon.stub();
    mongodbStub.toArray.resolves([{ id: 1 }, { id: 2 }]);
    await instance.getAllAuthors(callback);
    sinon.assert.calledWithExactly(mongodbStub.collection, 'authors');
    sinon.assert.calledWithExactly(mongodbStub.find, {});
    sinon.assert.calledOnce(mongodbStub.toArray);
    sinon.assert.calledWithExactly(callback, null, [{ id: 1 }, { id: 2 }]);
  });

  it('should handle error', async () => {
    const callback = sinon.stub();
    const error = new Error('network error');
    mongodbStub.toArray.rejects(error);
    await instance.getAllAuthors(callback);
    sinon.assert.calledWithExactly(callback, error);
  });
});

Результат модульного теста со 100% покрытием:


  59609593
    ✓ should find authors correctly
while fetching all authors in the book
    ✓ should handle error


  2 passing (14ms)

---------------|----------|----------|----------|----------|-------------------|
File           |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
---------------|----------|----------|----------|----------|-------------------|
All files      |      100 |      100 |      100 |      100 |                   |
 index.test.ts |      100 |      100 |      100 |      100 |                   |
 index.ts      |      100 |      100 |      100 |      100 |                   |
---------------|----------|----------|----------|----------|-------------------|

Обновление

Если вы используете оператор require / import для импорта ваши зависимости, например, пакет mongodb. Вот решение для модульного тестирования:

index-v2.js:

const { MongoClient } = require('mongodb');
const credentials = { URI: 'mongdb://127.0.0.1:27019' };
const mongoClient = new MongoClient(credentials.URI, { useUnifiedTopology: true });
mongoClient.connect();
const mongodb = mongoClient.db();

const errorHandler = {
  wrap(error, message) {
    console.log(message);
    return error;
  },
};

class SomeClass {
  async getAllAuthors(cb) {
    try {
      const result = await mongodb
        .collection('authors')
        .find({})
        .toArray();
      return cb(null, result);
    } catch (error) {
      return cb(errorHandler.wrap(error, 'while fetching all authors in the book'));
    }
  }
}

module.exports = SomeClass;

index-v2.test.js:

const sinon = require('sinon');
const mongodb = require('mongodb');

describe('59609593', () => {
  const mongodbStub = {
    connect: sinon.stub().returnsThis(),
    db: sinon.stub().returnsThis(),
    collection: sinon.stub().returnsThis(),
    find: sinon.stub().returnsThis(),
    toArray: sinon.stub(),
  };
  let instance;
  before(() => {
    sinon.stub(mongodb, 'MongoClient').callsFake(() => mongodbStub);
    const SomeClass = require('./index-v2');
    instance = new SomeClass();
  });

  afterEach(() => {
    sinon.restore();
  });

  it('should  find authors', async () => {
    mongodbStub.toArray.resolves([{ id: 1 }, { id: 2 }]);
    const callback = sinon.stub();
    await instance.getAllAuthors(callback);
    sinon.assert.calledWithExactly(mongodbStub.collection, 'authors');
    sinon.assert.calledWithExactly(mongodbStub.find, {});
    sinon.assert.calledOnce(mongodbStub.toArray);
    sinon.assert.calledWithExactly(callback, null, [{ id: 1 }, { id: 2 }]);
  });

  it('should handle error', async () => {
    const callback = sinon.stub();
    const error = new Error('network error');
    mongodbStub.toArray.rejects(error);
    await instance.getAllAuthors(callback);
    sinon.assert.calledWithExactly(callback, error);
  });
});

Результат модульного теста со 100% покрытием:

  59609593
    ✓ should  find authors
while fetching all authors in the book
    ✓ should handle error


  2 passing (74ms)

------------------|----------|----------|----------|----------|-------------------|
File              |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
------------------|----------|----------|----------|----------|-------------------|
All files         |      100 |      100 |      100 |      100 |                   |
 index-v2.js      |      100 |      100 |      100 |      100 |                   |
 index-v2.test.js |      100 |      100 |      100 |      100 |                   |
------------------|----------|----------|----------|----------|-------------------|

Исходный код: https://github.com/mrdulin/mongoose5.x-lab/tree/master/src/stackoverflow/59609593

...