Контейнер зависимостей узла не работает должным образом - PullRequest
0 голосов
/ 04 июня 2019

У меня есть DI-контейнер, подобный этому:

# di-container.js
const container = {
    fileReader: require("./file-reader"),
    csvReader: require("./csv-reader"),
}

module.exports = {
    container
}

И csv-reader.js выглядит так:

# csv-reader.js
const { container } = require("./di-container")

async function readFileAsCSV(path)
    const fileContents = await container.fileReader.readFileContents(path)
    return fileContents.split("\n")
                       .map(line => line.split(","))
}

У меня есть тестовый файл csv-reader.spec.js:

# csv-reader.spec.js
const { container } = require("./di-container")

describe("csvReader", () => {
    it("should read cells from file", async () => {
        const fakeCSV = "\"Name\",\"Age\"\n\"Bob Smith\",\"32\""
        container.fileReader.readFileContents = (_) => fakeCSV

        const result = container.csvReader.readFileAsCSV()

        # Do some assertions...
    })
})

При запуске теста происходит сбой с ошибкой (номера строк трассировки стека отличаются, как в примере немного отличается):

TypeError: Cannot read property 'fileReader' of undefined
 at Object.readFileAsCSV (csv-reader.js:8:42)
 at Context.it (csv-reader.spec.js:15:44)
 at processImmediate (internal/timers.js:443:21)

Я ожидал, что ссылка на память container одинакова в csv-reader.spec.js и csv-reader.js, поэтому я смогу изменить container.fileReader.readFileContents, и csv-reader будет использовать функцию макета.

Если я удаляю строку csvReader: require("./csv-reader") из di-container.js и использую const csvReader = require("./csv-reader") в csv-reader.spec.js, то тест проходит успешно. Это предполагает некоторую странность с порядком, в котором создаются зависимости в container.

Я попытался изменить порядок fileReader и csvReader в container и изменить их на container.fileReader = ... вместо встроенного экземпляра, но это не сработало. Jav

1 Ответ

0 голосов
/ 04 июня 2019

У вас есть зависимость цикл модуля .

Для файла di-container.js требуется csv-reader.js, а для файла csv-reader.js требуется di-container.js, что составляет цикл.

Из-за этого require("./di-container") возвращает null в файле csv-reader.js. Поскольку require("./di-container") равно null, деструктурированный container будет неопределенным. И, таким образом, вы получаете ошибку, которую вы упомянули.

Вам нужно изменить дизайн своих функций и подумать о том, где вы хотите их разместить.


На очень широком уровне просто выделите функции, которые должны использоваться в обоих файлах, и поместите их в common.js

Затем требуется common.js внутри csv-reader.js и di-container.js


Если я удалю строку csvReader: require ("./ csv-reader") из di-container.js и используйте const csvReader = require ("./ csv-reader") в csv-reader.spec.js, тогда тест проходит. Это предполагает некоторые странность с порядком, в котором находятся зависимости в контейнере создано.

Цикл прервался, когда вам не потребовалось csv-reader.js от di-container.js, и, следовательно, он работает просто отлично.

...