nodejs Невозможно заглушить синглтон в компонентном тесте - PullRequest
0 голосов
/ 11 июля 2020

Я пытаюсь заглушить функцию getDB в классе Connection, который является одноэлементным. Когда я делаю модульный тест для класса B, он работает нормально. Теперь я пытаюсь создать тест компонента, что означает использование класса A и снова заглушку функции getDB (класс A использует класс B, который использует класс соединения - getDb). Но заглушка не работает. Не уверен, почему.

Вот классы:

Class Connection

"use strict";

const config = {};
const pgp = require("pg-promise")();
const db = pgp(config);

class Connection {
    constructor() {
        console.log("Connection ctor")
    }

    getDb() {
        console.log("getDb")
        return db;
    }
}

module.exports = new Connection();

Class B

"use strict";

class B {
    constructor() {
        console.log("B ctor")
        this.db = require("./Connection").getDb();
    }

    async getDataFromDb() {
        console.log("B getDataFromDb")
        let res = null;
        res = await this.db.one("SELECT guid FROM table", ["NONE"]);
        return res.guid;
    }
}

module.exports = B;

Class A

"use strict";

const bDao = new (require("../db/B"))();

class A {
    async getGuid() {
        console.log("A getGuid")
        let guid = await bDao.getDataFromDb();
        console.log("got guid " + guid);
        return guid;
    }
}
module.exports = A;

The Test - B_unit_test работает, но когда я пытаюсь заглушить getDb из класса подключения, это не так. 'не заглушить его, и component_test завершится неудачно.

const chai = require("chai");
const expect = chai.expect;
const A = require("../src/service/A");
const Connection = require("../src/db/Connection");
const B = require("../src/db/B");
const sinon = require("sinon");

describe("component_test", function () {
    before(() => {
        var db = {
            one: async () => {
                return {
                    guid: '24f475b6-f9fa-495b-83f4-16f6b45b0a6a',
                    created_on: "123"
                }
            },
            none: async () => {
            }
        };
        this.dbStub = sinon.stub(Connection, "getDb").returns(db);
    });

    after(() => {
        this.dbStub.restore();
    });


    it("B_unit_test", async function () {
        var dao = new B();
        var guid = await dao.getDataFromDb();
        expect(guid).to.equal('24f475b6-f9fa-495b-83f4-16f6b45b0a6a');
    });

    it("A_component_test", async function () {
        var dao = new A();
        var guid = await dao.getGuid();
        expect(guid).to.equal('24f475b6-f9fa-495b-83f4-16f6b45b0a6a');
    });
});

1 Ответ

0 голосов
/ 15 июля 2020

Лучше заглушить getDataFromDb из B, который является классом, который A использовал напрямую. Решение для модульного тестирования:

connection.js:

const config = {};
const pgp = require('pg-promise')();
const db = pgp(config);

class Connection {
  constructor() {
    console.log('Connection ctor');
  }

  getDb() {
    console.log('getDb');
    return db;
  }
}

module.exports = new Connection();

b.js:

class B {
  constructor() {
    console.log('B ctor');
    this.db = require('./connection').getDb();
  }

  async getDataFromDb() {
    console.log('B getDataFromDb');
    let res = null;
    res = await this.db.one('SELECT guid FROM table', ['NONE']);
    return res.guid;
  }
}

module.exports = B;

b.test.js:

class B {
  constructor() {
    console.log('B ctor');
    this.db = require('./connection').getDb();
  }

  async getDataFromDb() {
    console.log('B getDataFromDb');
    let res = null;
    res = await this.db.one('SELECT guid FROM table', ['NONE']);
    return res.guid;
  }
}

module.exports = B;

a.js:

const bDao = new (require('./b'))();

class A {
  async getGuid() {
    console.log('A getGuid');
    let guid = await bDao.getDataFromDb();
    console.log('got guid ' + guid);
    return guid;
  }
}
module.exports = A;

a.test.js:

const B = require('./b');
const sinon = require('sinon');
const { expect } = require('chai');

describe('a', () => {
  it('should pass', async () => {
    const getDataFromDbStub = sinon.stub(B.prototype, 'getDataFromDb').resolves('24f475b6-f9fa-495b-83f4-16f6b45b0a6a');
    const A = require('./a');
    const aDao = new A();
    const guid = await aDao.getGuid();
    expect(guid).to.be.equal('24f475b6-f9fa-495b-83f4-16f6b45b0a6a');
    sinon.assert.calledOnce(getDataFromDbStub);
  });
});

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

  a
B ctor
getDb
A getGuid
got guid 24f475b6-f9fa-495b-83f4-16f6b45b0a6a
    ✓ should pass (47ms)

  b
B ctor
B getDataFromDb
    ✓ should pass


  2 passing (65ms)

---------------|---------|----------|---------|---------|-------------------
File           | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
---------------|---------|----------|---------|---------|-------------------
All files      |     100 |      100 |     100 |     100 |                   
 a.js          |     100 |      100 |     100 |     100 |                   
 b.js          |     100 |      100 |     100 |     100 |                   
 connection.js |     100 |      100 |     100 |     100 |                   
---------------|---------|----------|---------|---------|-------------------
...