I'm trying to test a function that is calling a resolved method from better-sqlite3 but it always tells me it's trying to read undefined.
These are my files.
./src/db.ts
import Database from "better-sqlite3";
//Create database
export const db = new Database("polychess.db");
./src/controllers/db-controllers.ts
import { db } from "../db";
const getAllPlayersDb = db.prepare("SELECT * FROM player");
export async function getDbStatus() {
const status = await db.open;
return {
message: `Database is ${status ? "online" : "offline"}`,
isOnline: status,
};
}
export async function getAllPlayersFromDB() {
return await getAllPlayersDb.all();
}
./src/__ test __/controllers/db-controllers.spec.ts
import {
getDbStatus,
getAllPlayersFromDB,
} from "../../controllers";
jest.mock("../../db");
const fakeTables = { players:[/*some players here*/] };
describe("Database controllers tests: ", () => {
afterAll(() => {
jest.resetAllMocks();
});
describe("Test getDbStatus()", () => {
it("Should return online status if DB is online", async () => {
db.open = true;
const dbStatus = await getDbStatus();
expect(dbStatus).toEqual({
message: `Database is online`,
isOnline: true,
});
});
it("Should return offline status if DB is offline", async () => {
db.open = false;
const dbStatus = await getDbStatus();
expect(dbStatus).toEqual({
message: `Database is offline`,
isOnline: false,
});
});
});
describe("Test getAllPlayersFromDB()", () => {
it("Should return all players", async () => {
db.prepare = jest.fn().mockImplementationOnce(() => {
return {
all: jest.fn(() => {
return fakeTables.players;
}),
};
});
expect(await getAllPlayersFromDB()).toEqual(fakeTables.players);
});
});
});
I tried different things like using requireActual but that breaks my first two tests. Also tried specifying "prepare" when mocking but I need to change its implementation for other functions I have planned...
It returns
TypeError: Cannot read properties of undefined (reading 'all')
When I change to use "require actual" my getDbStatus() returns
TypeError: Cannot set property open of #<Database> which has only a getter
When requiring actual I tried using jest.spyOn(db, "open", "get").mockReturnValueOnce(true); but it returns
Property 'open' is not declared configurable
Also tried
jest.mock("../../db", () => {
const originalDb =
jest.createMockFromModule<typeof import("../../db")>("../../db");
return {
db: {
open: false,
prepare: jest.fn(() => {
return { all: jest.fn(() => {return fakeTables.players;}) };
}),
},
};
});
But it changes implementation for all and I need different ones depending on my queries.