#javascript #unit-testing #mocha.js #sinon
#javascript #модульное тестирование #mocha.js #sinon
Вопрос:
У меня есть функция, которая возвращает список продуктов после чтения из файла json.
Я создал заглушку, чтобы имитировать поведение fs.readfile, но я хочу проверить исключение, генерируемое из функции, и для этого я хочу переопределить заглушку по умолчанию, чтобы возвращать null. Как мне этого добиться
моя функция
async getAllProducts() {
try {
// let rawData = fs.readFileSync("data/products.json");
// let data = JSON.parse(rawData);
// return data;
return JSON.parse(await fs.promises.readFile("data/products.json"));
} catch (error) {
if (error.message === "Unexpected end of JSON input") {
throw new NoProductsExistError("The File is Empty");
}
throw new FileReadingError("Error Reading File");
}
}
мой spec.js файл
// const assert = require("assert");
const chai = require("chai");
const expect = chai.expect;
const sinon = require("sinon");
const dao = require("./dao");
const fs = require("fs");
var sandbox;
beforeEach(() => {
sandbox = sinon.createSandbox();
sandbox
.stub(fs.promises, "readFile")
.withArgs("data/products.json")
.returns(
JSON.stringify([
{
productId: 101,
productName: "Sony XB450AP Wired Headset",
},
{
productId: 102,
productName: "Sony 1000XM3 Wired Headset",
}
])
);
});
describe("getAllProducts", () => {
it("should return all products", async () => {
// Here we are using the default stub of sinon got from the beforeEach
expect(await dao.getAllProducts()).to.deep.equal([
{
productId: 101,
productName: "Sony XB450AP Wired Headset",
},
{
productId: 102,
productName: "Sony 1000XM3 Wired Headset",
}
]);
});
it("should throw Error on Empty File", async () => {
// WANT TO OVERRIDE THE DEFAULT STUB TO RETURN NOTHING
// BELOW STUB DOES NOT WORK AND GIVES "TypeError: Attempted to wrap readFile which is already wrapped" ERROR
sinon
.stub(fs.promises, "readFile")
.withArgs("data/products.json")
.returns();
expect(await dao.getAllProducts()).to.throw(NoProductsExistError);
});
});
Как мне заставить вторую заглушку работать. Любая помощь очень ценится
Ответ №1:
Для тестирования лучше, если вы заглушаете / имитируете зависимость только один раз, а затем сбрасываете эту заглушку / макет перед каждым тестовым примером. Определите, что зависимость должна делать для каждого тестового примера.
// const assert = require("assert");
const chai = require("chai");
const expect = chai.expect;
const sinon = require("sinon");
const dao = require("./dao");
const fs = require("fs");
describe("getAllProducts", () => {
var sandbox;
var fsReadFileStub;
before(() => {
sandbox = sinon.createSandbox();
fsReadFileStub = sandbox.stub(fs.promises, "readFile")
});
afterEach(() => {
fsReadFileStub.reset();
})
it("should return all products", async () => {
fsReadFileStub.withArgs("data/products.json")
.returns(
JSON.stringify([
{
productId: 101,
productName: "Sony XB450AP Wired Headset",
},
{
productId: 102,
productName: "Sony 1000XM3 Wired Headset",
}
])
);
expect(await dao.getAllProducts()).to.deep.equal([
{
productId: 101,
productName: "Sony XB450AP Wired Headset",
},
{
productId: 102,
productName: "Sony 1000XM3 Wired Headset",
}
]);
});
it("should throw Error on Empty File", async () => {
fsReadFileStub
.stub(fs.promises, "readFile")
.withArgs("data/products.json")
.returns();
expect(await dao.getAllProducts()).to.throw(NoProductsExistError);
});
});