Napisałem funkcję javascript, która tworzy obiekt z biblioteki wymagań () "D, a następnie go używa. Wydaje się, że powoduje, że kłopoty, gdy próbuję pisać testy na to, ponieważ nie wydawałam się mieć dobrego sposobu, aby uzyskać kontrolę nad tym obiektem i stworzyć udawane metodami, aby przetestować zachowanie mojej funkcji.

Wracam do tego, ponieważ słabo zaprojektowałem funkcję? Pochodzę z tła java / wiosny, więc głosy w mojej głowie krzyczą "wtrysku zależności". Czy jest lepszy sposób, aby to zrobić, niż tylko przekazanie obiektu Moja funkcja potrzebuje do niego jako parametr?

Przykładowa funkcja:

// dbService.js
const AWS = require('aws-sdk');

function getItem() {
    const dynamo = new AWS.DynamoDB.DocumentClient();
    var params = {/* irrelevant */}

    try {
        return await dynamo.get(getParams).promise();
    } catch (err) {
        return err;
    }
}

exports.getItem = getItem;

Zaczynam biegać w zacięciach, gdy próbuję pisać testy, aby zweryfikować zachowanie mojego funkcji, gdy dynamo.get() powraca z powodzeniem lub rzuca błąd.

Przykładowy test (używam sinon do wyśmiewania i Chai do twierdzenia):

// dbServiceTest.js
const sinon = require('sinon');
const dbService = require('dbService.js');
const expect = require('chai').expect;

describe('dbService: When database returns a record', function() {
    let dbMock, dbServiceResp = null;

    beforeEach(async function() {
        dbMock = sinon.stub(dynamo, "get")
            .returns({Item: "an item"});
        dbServiceResp = await dbService.getItem("an item");
    });

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

    it('Should have expected value', function() {
        expect(dbServiceResp.Item).to.be.equal("an item");
    });
});

Wydaje się oczywiste, że stworzyłem próbę dynamo.get() nie jest używany przez dbService.getItem(), ponieważ dbService.getItem() całkowicie posiada instancję własnej zależności od obiektu {x3}}.

Czy powinienem po prostu przekazać DocumentClient w funkcję mojego {x1}}, czy jest lepszy?

0
Ubunfu 28 październik 2020, 07:25

1 odpowiedź

Najlepsza odpowiedź

DI jest najlepszym sposobem, aby Twój kod był łatwiejszy do testowania, lepszej skalowalności i oddzielić moduły. Ale nadal możesz skrócić moduł aws-sdk, jeśli chcesz require moduł jako zależność. Rozwiązanie testowe jednostkowe:

dbService.js:

const AWS = require('aws-sdk');

async function getItem() {
  const dynamo = new AWS.DynamoDB.DocumentClient();
  var params = {
    /* irrelevant */
  };

  try {
    return await dynamo.get(params).promise();
  } catch (err) {
    return err;
  }
}

exports.getItem = getItem;

dbService.test.js:

const sinon = require('sinon');
const AWS = require('aws-sdk');
const expect = require('chai').expect;

describe('dbService: When database returns a record', function() {
  afterEach(() => {
    sinon.restore();
  });
  it('Should have expected value', async function() {
    const mDynamo = { get: sinon.stub().returnsThis(), promise: sinon.stub().resolves({ Item: 'an item' }) };
    const mDocumentClient = sinon.stub(AWS.DynamoDB, 'DocumentClient').returns(mDynamo);
    const dbService = require('./dbService');
    const actual = await dbService.getItem();
    expect(actual.Item).to.be.equal('an item');
    sinon.assert.calledOnce(mDocumentClient);
    sinon.assert.calledWithExactly(mDynamo.get, {});
    sinon.assert.calledOnce(mDynamo.promise);
  });

  it('should return error', async () => {
    const mError = new Error('network');
    const mDynamo = { get: sinon.stub().returnsThis(), promise: sinon.stub().rejects(mError) };
    const mDocumentClient = sinon.stub(AWS.DynamoDB, 'DocumentClient').returns(mDynamo);
    const dbService = require('./dbService');
    const actual = await dbService.getItem();
    expect(actual.message).to.be.eql('network');
    sinon.assert.calledOnce(mDocumentClient);
    sinon.assert.calledWithExactly(mDynamo.get, {});
    sinon.assert.calledOnce(mDynamo.promise);
  });
});

Wynik testu jednostkowego:

  dbService: When database returns a record
    ✓ Should have expected value
    ✓ should return error


  2 passing (26ms)

--------------|---------|----------|---------|---------|-------------------
File          | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
--------------|---------|----------|---------|---------|-------------------
All files     |     100 |      100 |     100 |     100 |                   
 dbService.js |     100 |      100 |     100 |     100 |                   
--------------|---------|----------|---------|---------|-------------------
0
slideshowp2 28 październik 2020, 05:47