Deno 在单元测试中模拟命名导入
Deno mock out named import in unit test
我想对使用 jsonfile
读取数据的模块进行单元测试。
import * as jsonfile from 'https://deno.land/x/jsonfile/mod.ts'
想模拟出 jsonfile.readJsonSync 到 return 测试数据并避免写入磁盘。这能做到吗?
希望这个抽象示例描述了我想要归档的内容:
index.ts
import * as jsonfile from 'https://deno.land/x/jsonfile/mod.ts'
export function readAndReturn() {
return jsonfile.readJsonSync('./example.json')
}
index.test.ts
import { assertEquals } from 'https://deno.land/std@0.112.0/testing/asserts.ts'
import { readAndReturn } from './index.ts'
const dataFixture = {hello: "word"}
// mock out jsonfile.readJsonSync to return dataFixture and not the actual file content
Deno.test("Reads the data", () => {
assertEquals(readAndReturn(), dataFixture)
})
解决方案
非常感谢@mfulton26 和@jsejcksn 为我指明了正确的方向。
unit.test.importmap.json
{
"imports": {
"https://deno.land/x/jsonfile/mod.ts": "./mocks/jsonfile.ts"
}
}
mocks/jsonfile.ts
import sinon from 'https://cdn.skypack.dev/sinon@11.1.2?dts'
const readJsonSync = sinon.stub()
const writeJsonSync = sinon.stub()
export { readJsonSync, writeJsonSync }
index.test.ts
import { readJsonSync as readJsonSyncMock } from './mocks/jsonfile.ts'
Deno.test(
'Reads the data', () => {
const data = ["hello world"]
readJsonSyncMock.withArgs(`./example.json`).returns(data)
assertEquals(readAndReturn(), data)
}
)
deno test --import-map=unit.test.importmap.json
ES 模块不能存根。
然而,您可以将要存根的功能包装在 class 或对象中并导出,然后您可以使用 Sinon.JS 或其他库在其上存根方法。
要开始在 Deno 中使用 Sinon.JS,我建议查看 Integration with testing libraries | Testing | Manual | Deno which references a sinon_example.ts。
您可以使用 import map 替换模块。
只需创建一个包含模拟函数的本地模块 ./jsonfile.mock.ts
,然后使用与 https://deno.land/x/jsonfile/mod.ts
中的真实模块相同的名称导出它们。然后,创建一个具有正确映射的导入映射,并在 运行 你的测试时使用它:
./jsonfile.mock.ts
:
export function readJsonSync (filePath: string): unknown {
// implement mocked fn
}
// and any other imports you use from the module
./index.importmap.json
:
{
"imports": {
"https://deno.land/x/jsonfile/mod.ts": "./jsonfile.mock.ts"
}
}
deno test --import-map=index.importmap.json index.test.ts
在某些情况下,用另一个模块包装您的模块可能会奏效,但如果您的模块有副作用并且其中有错误,这将不起作用。
我创建了一个小模块来解决这个问题:Fake Imports。
可能无法模拟静态导入,但肯定可以模拟动态导入!
用法
import { Importer } from "https://deno.land/x/fake_imports/mod.js";
const importer = new Importer(import.meta.url);
importer.fakeModule("https://deno.land/x/jsonfile/mod.ts", `
function readJsonSync() {}
export {readJsonSync};
`);
// Then load your main module asynchronously
const mainModule = await importer.import("./main.ts");
// And perform your test on mainModule like you usually would
我想对使用 jsonfile
读取数据的模块进行单元测试。
import * as jsonfile from 'https://deno.land/x/jsonfile/mod.ts'
想模拟出 jsonfile.readJsonSync 到 return 测试数据并避免写入磁盘。这能做到吗?
希望这个抽象示例描述了我想要归档的内容:
index.ts
import * as jsonfile from 'https://deno.land/x/jsonfile/mod.ts'
export function readAndReturn() {
return jsonfile.readJsonSync('./example.json')
}
index.test.ts
import { assertEquals } from 'https://deno.land/std@0.112.0/testing/asserts.ts'
import { readAndReturn } from './index.ts'
const dataFixture = {hello: "word"}
// mock out jsonfile.readJsonSync to return dataFixture and not the actual file content
Deno.test("Reads the data", () => {
assertEquals(readAndReturn(), dataFixture)
})
解决方案
非常感谢@mfulton26 和@jsejcksn 为我指明了正确的方向。
unit.test.importmap.json
{
"imports": {
"https://deno.land/x/jsonfile/mod.ts": "./mocks/jsonfile.ts"
}
}
mocks/jsonfile.ts
import sinon from 'https://cdn.skypack.dev/sinon@11.1.2?dts'
const readJsonSync = sinon.stub()
const writeJsonSync = sinon.stub()
export { readJsonSync, writeJsonSync }
index.test.ts
import { readJsonSync as readJsonSyncMock } from './mocks/jsonfile.ts'
Deno.test(
'Reads the data', () => {
const data = ["hello world"]
readJsonSyncMock.withArgs(`./example.json`).returns(data)
assertEquals(readAndReturn(), data)
}
)
deno test --import-map=unit.test.importmap.json
ES 模块不能存根。
然而,您可以将要存根的功能包装在 class 或对象中并导出,然后您可以使用 Sinon.JS 或其他库在其上存根方法。
要开始在 Deno 中使用 Sinon.JS,我建议查看 Integration with testing libraries | Testing | Manual | Deno which references a sinon_example.ts。
您可以使用 import map 替换模块。
只需创建一个包含模拟函数的本地模块 ./jsonfile.mock.ts
,然后使用与 https://deno.land/x/jsonfile/mod.ts
中的真实模块相同的名称导出它们。然后,创建一个具有正确映射的导入映射,并在 运行 你的测试时使用它:
./jsonfile.mock.ts
:
export function readJsonSync (filePath: string): unknown {
// implement mocked fn
}
// and any other imports you use from the module
./index.importmap.json
:
{
"imports": {
"https://deno.land/x/jsonfile/mod.ts": "./jsonfile.mock.ts"
}
}
deno test --import-map=index.importmap.json index.test.ts
在某些情况下,用另一个模块包装您的模块可能会奏效,但如果您的模块有副作用并且其中有错误,这将不起作用。
我创建了一个小模块来解决这个问题:Fake Imports。
可能无法模拟静态导入,但肯定可以模拟动态导入!
用法
import { Importer } from "https://deno.land/x/fake_imports/mod.js";
const importer = new Importer(import.meta.url);
importer.fakeModule("https://deno.land/x/jsonfile/mod.ts", `
function readJsonSync() {}
export {readJsonSync};
`);
// Then load your main module asynchronously
const mainModule = await importer.import("./main.ts");
// And perform your test on mainModule like you usually would