Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 30 additions & 16 deletions examples/tutorials/stubbing.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,23 @@ Here's a simple example demonstrating how to stub a function:
import { assertEquals } from "jsr:@std/assert";
import { stub } from "jsr:@std/testing/mock";

// Original function
function getUserName(id: number): string {
// In a real app, this might call a database
return "Original User";
}
// Wrap dependencies so they can be stubbed safely from tests.
const deps = {
getUserName(_id: number): string {
// In a real app, this might call a database
return "Original User";
},
};

// Function under test
function greetUser(id: number): string {
const name = getUserName(id);
const name = deps.getUserName(id);
return `Hello, ${name}!`;
}

Deno.test("greetUser with stubbed getUserName", () => {
// Create a stub that returns a controlled value
const getUserNameStub = stub(globalThis, "getUserName", () => "Test User");
const getUserNameStub = stub(deps, "getUserName", () => "Test User");

try {
// Test with the stubbed function
Expand Down Expand Up @@ -136,17 +138,21 @@ import { returnsNext, stub } from "jsr:@std/testing/mock";
import { assertEquals } from "jsr:@std/assert";

Deno.test("stub with multiple return values", () => {
const dataService = {
fetchData: () => "original data",
};

const fetchDataStub = stub(
globalThis,
dataService,
"fetchData",
// Return these values in sequence
returnsNext(["first result", "second result", "third result"]),
);

try {
assertEquals(fetchData(), "first result");
assertEquals(fetchData(), "second result");
assertEquals(fetchData(), "third result");
assertEquals(dataService.fetchData(), "first result");
assertEquals(dataService.fetchData(), "second result");
assertEquals(dataService.fetchData(), "third result");
} finally {
fetchDataStub.restore();
}
Expand All @@ -165,8 +171,12 @@ Deno.test("stub with custom implementation", () => {
// Create a counter to track how many times the stub is called
let callCount = 0;

const mathService = {
calculate: (a: number, b: number) => a + b,
};

const calculateStub = stub(
globalThis,
mathService,
"calculate",
(a: number, b: number) => {
callCount++;
Expand All @@ -175,7 +185,7 @@ Deno.test("stub with custom implementation", () => {
);

try {
const result = calculate(5, 10);
const result = mathService.calculate(5, 10);
assertEquals(result, 25); // 5 + (10 * 2)
assertEquals(callCount, 1);
} finally {
Expand All @@ -192,8 +202,12 @@ One of the most common uses of stubs is to replace API calls during testing:
import { assertEquals } from "jsr:@std/assert";
import { stub } from "jsr:@std/testing/mock";

const apiClient = {
fetch: globalThis.fetch,
};

async function fetchUserData(id: string) {
const response = await fetch(`https://api.example.com/users/${id}`);
const response = await apiClient.fetch(`https://api.example.com/users/${id}`);
if (!response.ok) {
throw new Error(`Failed to fetch user: ${response.status}`);
}
Expand All @@ -206,9 +220,9 @@ Deno.test("fetchUserData with stubbed fetch", async () => {
{ status: 200, headers: { "Content-Type": "application/json" } },
);

// Replace global fetch with a stubbed version
// Replace apiClient.fetch with a stubbed version
const fetchStub = stub(
globalThis,
apiClient,
"fetch",
() => Promise.resolve(mockResponse),
);
Expand Down