Introduction
Testing JavaScript code ensures your apps don’t break as they grow. The modern JS ecosystem provides powerful testing tools like Jest, Mocha, Vitest, Cypress, and Playwright. This tutorial covers unit tests, integration tests, mocking, and best practices.
1. What Are Unit Tests?
Unit tests check single functions or components.
// example function
function add(a, b) { return a + b; }
// test
test("adds numbers", () => {
expect(add(2, 3)).toBe(5);
});
2. Installing Jest (Node.js)
npm install --save-dev jest
Add to package.json:
"scripts": {
"test": "jest"
}
3. Basic Jest Test File
// math.js
export function multiply(a, b) {
return a * b;
}
// math.test.js
import { multiply } from "./math.js";
test("multiply works", () => {
expect(multiply(4, 5)).toBe(20);
});
4. Testing Asynchronous Code
async function fetchUser() {
return "Kaloyan";
}
test("async test", async () => {
const user = await fetchUser();
expect(user).toBe("Kaloyan");
});
5. Mocking Functions
const sendEmail = jest.fn();
test("email sent", () => {
sendEmail("hello");
expect(sendEmail).toHaveBeenCalledWith("hello");
});
6. Mocking Modules
jest.mock("./api.js", () => ({
getUser: () => "MockUser"
}));
7. Snapshot Testing (UI)
expect(renderedHTML).toMatchSnapshot();
8. Using Vitest (Faster Alternative)
npm install -D vitest
// test
import { describe, it, expect } from "vitest";
describe("math", () => {
it("works", () => {
expect(2 + 2).toBe(4);
});
});
9. Browser Testing (Cypress)
npm install cypress --save-dev
npx cypress open
10. E2E Example
// cypress test
cy.visit("https://codetweakrs.net");
cy.contains("Tutorials").click();
11. Testing DOM Manipulation
document.body.innerHTML = `
<button id="btn">Click</button>
`;
document.getElementById("btn").click();
12. Testing Fetch Calls
global.fetch = jest.fn(() =>
Promise.resolve({
json: () => Promise.resolve({ name: "Kaloyan" })
})
);
test("fetch user", async () => {
const res = await fetch("/api");
const data = await res.json();
expect(data.name).toBe("Kaloyan");
});
13. Code Coverage
npm test -- --coverage
14. Useful Assertions
expect(value).toBeDefined();
expect(value).toBeNull();
expect(arr).toContain(10);
expect(obj).toMatchObject({ username: "Kaloyan" });
15. Best Practices
- Test small pieces of code
- Mock external APIs
- Use descriptive test names
- Keep test files next to source code
- Automate tests with CI/CD
- Test user behavior, not just function outputs
Summary
- Jest → best all-around testing tool
- Vitest → super fast, Vite-friendly
- Cypress/Playwright → browser & E2E testing
- Mocking lets you isolate components
- Coverage helps find untested code paths