numberkruncher
numberkruncher•9mo ago

How to mock modules like you can with jest?

With node/jest I was able to mock specific functions from modules using jest.mock at the start of the test file. How can I do this in Deno? I have a module which calls a function from another module:
import {foo} from "foo";

export function bar(a: number): number {
return foo(a * 2);
}
import {foo} from "foo";

export function bar(a: number): number {
return foo(a * 2);
}
How can I substitute foo with a mock/stub/fake for the scope of a test file?
jest.mock("foo", () => ({
foo: jest.fn();
}));

import {foo} from "foo";

describe("example", () => {
it("returns the expected number", () => {
foo.mockImplementation((_) => 100);
...
jest.mock("foo", () => ({
foo: jest.fn();
}));

import {foo} from "foo";

describe("example", () => {
it("returns the expected number", () => {
foo.mockImplementation((_) => 100);
...
7 Replies
Deno AI Helper
Deno AI Helper•9mo ago
In Deno, you can achieve similar functionality to jest.mock using the mocking utilities provided in the Deno standard library. The documentation describes two basic mock types: spy and stub, along with assertion functions dedicated to these types. A spy is a type of object that records every interaction with it, and you can assert an interaction occurred later. A stub is an object that simulates some predefined behavior. Here's an example of how you might use a spy to wrap a function:
import sinon from "npm:sinon";
import { assertEquals } from "https://deno.land/std@release-2024.05.07/assert/mod.ts";
import { bar, funcs } from "./my_module.js";

Deno.test("calls foo during execution of bar", () => {
// Create a test spy that wraps 'foo' on the 'funcs' object
const spy = sinon.spy(funcs, "foo");

// Call function 'bar' with an argument
bar(2);

// Assert that 'foo' was called with the expected argument
assertEquals(spy.calledWith(4), true);
});
import sinon from "npm:sinon";
import { assertEquals } from "https://deno.land/std@release-2024.05.07/assert/mod.ts";
import { bar, funcs } from "./my_module.js";

Deno.test("calls foo during execution of bar", () => {
// Create a test spy that wraps 'foo' on the 'funcs' object
const spy = sinon.spy(funcs, "foo");

// Call function 'bar' with an argument
bar(2);

// Assert that 'foo' was called with the expected argument
assertEquals(spy.calledWith(4), true);
});
In this example, funcs would be an object exported from my_module.js that contains the foo function you want to spy on. You would then import funcs and bar into your test file and create a spy on foo using sinon.spy. For stubbing, you can use the stub function from the Deno standard library's mocking utilities:
import {
returnsNext,
stub,
} from "https://deno.land/std@0.136.0/testing/mock.ts";
import { assertEquals } from "https://deno.land/std@0.136.0/testing/asserts.ts";

Deno.test("how stub works", () => {
const mathStub = stub(Math, "random", returnsNext([0.1, 0.2, 0.3]));
try {
assertEquals(Math.random(), 0.1);
assertEquals(Math.random(), 0.2);
assertEquals(Math.random(), 0.3);
} finally {
mathStub.restore();
}
});
import {
returnsNext,
stub,
} from "https://deno.land/std@0.136.0/testing/mock.ts";
import { assertEquals } from "https://deno.land/std@0.136.0/testing/asserts.ts";

Deno.test("how stub works", () => {
const mathStub = stub(Math, "random", returnsNext([0.1, 0.2, 0.3]));
try {
assertEquals(Math.random(), 0.1);
assertEquals(Math.random(), 0.2);
assertEquals(Math.random(), 0.3);
} finally {
mathStub.restore();
}
});
In your
Deno AI Helper
Deno AI Helper•9mo ago
case, you would create a stub for the foo function and then use it in your tests. Remember that you would need to export the object containing the foo function so that you can replace it with a stub in your tests. Please note that the examples provided here are based on the documentation and may require adjustments to fit the specific structure of your modules and tests. 🦕
woife
woife•2mo ago
It seems that this is not possible with deno.
magicrobots
magicrobots•2mo ago
Yeah I'm working on a deno react app and have found Deno sucks for front end testing and I'm pretty bummed about it. I feel like I'm missing something because the whole beauty of Deno was that I wouldn't have to deal with Jest and its baloney, but here we are having to implement Jest because Deno is useless for this usecase. Giant bummer Looks like my usecase is different from yours; I'm trying to get it to render react components not mock functions
woife
woife•2mo ago
It looks like the use cases are different but the root cause is the same I would say. In this section deno seems to be to immature atm. I was also really hyped about having all the tool set in one place to finally get rid of jest. Unfortunately it seems that there is to less pressure in this direction on the projects. This surprises me because does that mean all the other user do not or at least much less testing??? On the other hand this might be an opportunity to see things from a different perspective. I might restructure my tests in a way that I do not need the mock anymore. May this also be the case for you?
magicrobots
magicrobots•2mo ago
I have been thinking about how to run tests without rendering the components, but haven't come up with a decent solution yet 🤔
woife
woife•2mo ago
The last resort for me was to use jest with deno (which completely goes against my intention to leave node in the first place) but I could not get it to run. Using jest was the recommendation from someone of the deno team in a github issue about the topic. They seem to have other priorities atm. I quit the deno experiment for now maybe I try again in some months.

Did you find this page helpful?