Compare and contrast Mocks and Stubs as types of test doubles. Provide a specific Node.js testing scenario where a Mock would be more appropriate than a Stub, and vice versa.
Node.js interview question for Advanced practice.
Answer
Comparison: Stubs provide pre-programmed, 'canned' responses to method calls made during a test. They are used when your test needs a dependency to return a specific value to continue. This is often called 'state verification'. You check if the code under test returns the correct result based on the stubbed input. Mocks are objects that have expectations about how they will be used. You program a mock with the calls it expects to receive. Mocks are used to verify that certain methods were called on the dependency. This is often called 'behavior verification'. You check if the code under test performed the correct actions. Scenario for a Stub: Imagine a function getUserGreeting(userId) that fetches a user from a service and returns a greeting. To test this, you don't care how the user service works, you just need it to return a user object. Appropriate Choice: A Stub. You would stub the userService.findById(userId) method to return a specific user object (e.g., { name: 'Alice' }). Your test would then assert that getUserGreeting returns 'Hello, Alice'. Scenario for a Mock: Imagine a function deleteUser(userId) that should call a logging service before deleting a user from a database. Appropriate Choice: A Mock. The return value of the logger doesn't matter, but it's critical that it was called. You would mock the loggingService and set an expectation that its log method is called with a specific message. Your test would then assert that the mock's expectation was met.
Explanation
Martin Fowler, who popularized the term 'test double', distinguishes mocks from other doubles by their ability to verify interactions.