我有一个这样的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 = ...
而不是内联实例化,但这没有用。
答案 0 :(得分:0)
您有一个依赖项module cycle。
您的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
,那么周期就中断了,因此一切正常。