Переопределить заглушку sinon для конкретного модульного тестового примера в JS

#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);
    });
});