好测试与差测试
好测试
Integration-style: 通过真实 interface 测试,非 mock 内部部件。
// GOOD: Tests observable behavior
test("user can checkout with valid cart", async () => {
const cart = createCart();
cart.add(product);
const result = await checkout(cart, paymentMethod);
expect(result.status).toBe("confirmed");
});
特征:
- 测试用户/caller 关心的 behavior
- 仅使用 public API
- 能在 internal refactor 后存活
- 描述 WHAT,非 HOW
- 每个 test 一个 logical assertion
差测试
Implementation-detail tests:与 internal structure 耦合。
// BAD: Tests implementation details
test("checkout calls paymentService.process", async () => {
const mockPayment = jest.mock(paymentService);
await checkout(cart, payment);
expect(mockPayment.process).toHaveBeenCalledWith(cart.total);
});
危险信号:
- Mock internal collaborator
- 测试 private method
- 断言 call count/order
- refactor 未改 behavior 时 test 仍 break
- test 名描述 HOW 而非 WHAT
- 绕过 interface 验证
// BAD: Bypasses interface to verify
test("createUser saves to database", async () => {
await createUser({ name: "Alice" });
const row = await db.query("SELECT * FROM users WHERE name = ?", ["Alice"]);
expect(row).toBeDefined();
});
// GOOD: Verifies through interface
test("createUser makes user retrievable", async () => {
const user = await createUser({ name: "Alice" });
const retrieved = await getUser(user.id);
expect(retrieved.name).toBe("Alice");
});