Phân biệt thực tế: Stub cung cấp canned response không quan tâm đến cách gọi — jest.fn().mockReturnValue(user) để feed data cho SUT (system under test). Mock verify interactions — expect(emailService.send).toHaveBeenCalledWith(email) để đảm bảo behavior đúng. Fake có working implementation đơn giản hơn — in-memory repository thay vì real DB, fake email service lưu vào array.
- Hướng dẫn thực tế: dùng Stub khi test chỉ cần control input data (không care về side effects); dùng Mock khi hành động quan trọng phải xảy ra (email gửi, event emit, payment charge); dùng Fake khi cần nhiều interactions với dependency (5 operations trên DB) — fake in-memory repo nhanh và realistic hơn 5 mock calls.
- Over-mocking smell: nếu test cần mock > 3-4 dependencies, đó là dấu hiệu design issue (too many dependencies → god class).
- Test với real implementation khi có thể (fast enough, no external I/O) — integration > unit với mocks cho confidence.
- Lưu ý: mock quá nhiều → tests pass nhưng integration fails (mock không reflect thực tế API).
Practical distinctions: Stub provides a canned response regardless of how it's called — jest.fn().mockReturnValue(user) to feed data to the SUT. Mock verifies interactions — expect(emailService.send).toHaveBeenCalledWith(email) ensures the correct behavior occurred. Fake has a simpler but working implementation — an in-memory repository instead of a real DB, a fake email service that saves to an array.
- Practical guidance: use Stub when a test only needs to control input data (doesn't care about side effects); use Mock when an important action must occur (email sent, event emitted, payment charged); use Fake when many interactions with a dependency are needed (5 DB operations) — an in-memory fake repo is faster and more realistic than 5 separate mock calls.
- Over-mocking smell: if a test needs more than 3-4 mocks, that signals a design issue (too many dependencies → god class).
- Test with real implementations when possible (fast enough, no external I/O) — integration tests beat unit tests with mocks for confidence.
Pitfall: over-mocking → tests pass but integration fails because mocks don't reflect the real API.