Devin
发布于 2025-09-17 / 0 阅读
0
0

Jest quickstart

Installation and Setup

npm install --save-dev jest

Basic Test Structure

// file.test.js|ts
describe("Subject of something to test", () => {
  describe("block1", () => {
    test("test point1-1", () => {
      // test content
    });
    
    it("test point1-2", () => {
      // test content
    });
  });
  
  describe("block2", () => {
    it("test point2-1", () => {
      // test content
    });
    
    it("test point2-2", () => {
      // test content
    });
  });
});

Running Tests

# Run all tests
jest

# Run single test file
jest path/to/my-test.js

# Test specific directory
jest api/

# Filter tests by filename pattern
jest --testPathPattern=api

# Match tests by name pattern
jest -t "Math"  # Matches describe("Math test", fn)

Test Scope Control

// Run only this test in a suite
it.only("test example", fn)

// Skip this test
it.skip("test example", fn)

Setup and Teardown

Global Setup (jest.config.js)

module.exports = {
  setupFiles: ["./tests/setup.ts"],
};

Setup File (setup.ts)

// Global setup (runs once before all tests)
beforeAll(() => {
  // Connect to test database
});

// Global teardown (runs once after all tests)
afterAll(() => {
  // Drop database or close connection
});

Scoped Setup (within test file)

// Applies to all tests in this file
beforeEach(() => {
  return initializeCityDatabase();
});

test('city database has Vienna', () => {
  expect(isCity('Vienna')).toBeTruthy();
});

describe('matching cities to foods', () => {
  // Applies only to tests in this describe block
  beforeEach(() => {
    return initializeFoodDatabase();
  });

  test('Vienna <3 veal', () => {
    expect(isValidCityFoodPair('Vienna', 'Wiener Schnitzel')).toBe(true);
  });
});

Common Matchers

Basic Equality

expect(fn).toBe(value)        // Strict equality (===)
expect(n).not.toBe(value)     // Negation
expect(fn).toEqual(value)     // Value equality

Truthiness

expect(n).toBeNull();
expect(n).toBeDefined();
expect(n).not.toBeUndefined();
expect(n).not.toBeTruthy();
expect(n).toBeFalsy();        // Matches false, null, undefined, "", 0

Numbers

expect(value).toBeGreaterThan(3);
expect(value).toBeGreaterThanOrEqual(3.5);
expect(value).toBeLessThan(5);
expect(value).toBeLessThanOrEqual(4.5);

Strings

expect(string).toMatch(/stop/);
expect(string).not.toMatch(/I/);

Exceptions

function compileAndroidCode() {
  throw new Error('you are using the wrong JDK!');
}

test('compiling android goes as expected', () => {
  expect(() => compileAndroidCode()).toThrow();
  expect(() => compileAndroidCode()).toThrow(Error);
  expect(() => compileAndroidCode()).toThrow("error message");
});

Functions

// The mock function was called at least once
expect(mockFunc).toHaveBeenCalled();

// Called with specific arguments
expect(mockFunc).toHaveBeenCalledWith(arg1, arg2);

// Last call was with specific arguments
expect(mockFunc).toHaveBeenLastCalledWith(arg1, arg2);

// Compare to snapshot
expect(mockFunc).toMatchSnapshot();

Mock Functions

Basic Mock Usage

// forEach.js
export function forEach(items, callback) {
  for (const item of items) {
    callback(item);
  }
}

// Test file
import { forEach } from './forEach';

test("test a function using mock parameter", () => {
  const mockCb = jest.fn(x => x + 3);
  
  forEach([0, 1], mockCb);
  
  // Called 2 times
  expect(mockCb.mock.calls).toHaveLength(2);
  
  // First argument of first call was 0
  expect(mockCb.mock.calls[0][0]).toBe(0);
  
  // Return value of first call was 3
  expect(mockCb.mock.results[0].value).toBe(3);
});

Mock Return Values

const myMock = jest.fn();
myMock.mockReturnValueOnce(10)
       .mockReturnValueOnce('x')
       .mockReturnValue(true);

console.log(myMock()); // 10
console.log(myMock()); // 'x'
console.log(myMock()); // true

Mock Implementations

const myMockFn = jest
  .fn()
  .mockReturnValue('default')
  .mockImplementation(scalar => 42 + scalar)
  .mockName('add42'); // Custom name for error messages

Mocking Modules

// app.js
import { add } from './math';

export function calculateTotal(x, y) {
  return add(x, y);
}

// Test file
import * as math from './math';
import { calculateTotal } from './app';

jest.mock('./math'); // Automatically replaces all exports with mocks

test('calculateTotal uses mocked add', () => {
  math.add.mockReturnValue(100);
  
  const result = calculateTotal(1, 2); // Returns 100 instead of 3
  expect(result).toBe(100);
});

Important Note on TypeScript Support

Although Jest is a classical full-functional testing framework, its native support for TypeScript is limited and relies on Babel for transpilation. This can lead to complex configuration and sometimes suboptimal developer experience.

For better TypeScript integration, consider these alternatives:

  1. ts-jest: A Jest transformer with source map support that lets you use Jest to test projects written in TypeScript.

  2. Vitest: A modern testing framework built on Vite that provides excellent TypeScript support out of the box, with faster execution and a more intuitive developer experience. Many developers report significantly better testing experiences with Vitest when working with TypeScript projects.


评论