Both mocks and stubs are concepts used in testing, especially in the context of unit testing and test doubles. They are used to isolate the code under test from its dependencies.
Mock: A mock is an object that simulates the behavior of a real object or component, allowing you to set expectations on its methods and verify interactions. Mocks are often used to ensure that specific methods are called with the correct parameters during testing.
Stub: A stub is an object that provides pre-defined responses to method calls, typically to isolate the code under test from complex behavior or external systems. Stubs allow you to control the behavior of certain methods for the purpose of testing.
Example:
Let's consider a simple example where you're testing a PaymentProcessor
class that interacts with a PaymentGateway
object to process payments. The PaymentGateway
communicates with a payment provider to process actual payments.
java
public interface PaymentGateway {
boolean processPayment(double amount);
}
public class PaymentProcessor {
private PaymentGateway gateway;
public PaymentProcessor(PaymentGateway gateway) {
this.gateway = gateway;
}
public boolean processOrder(double totalAmount) {
if (totalAmount <= 0) {
return false;
}
return gateway.processPayment(totalAmount);
}
}
In a unit test for the PaymentProcessor
class, you might want to isolate it from the actual payment gateway to focus on testing its behavior. Here's how mocks and stubs could be used in this scenario:
Mock Example:
You want to ensure that the processPayment
method of the PaymentGateway
is called with the correct amount during testing. You use a mock to set this expectation and verify the interaction:
java
import org.junit.Test;
import static org.mockito.Mockito.*;
public class PaymentProcessorTest {
@Test
public void testProcessOrderCallsPaymentGateway() {
PaymentGateway mockGateway = mock(PaymentGateway.class);
PaymentProcessor processor = new PaymentProcessor(mockGateway);
double totalAmount = 100.0;
processor.processOrder(totalAmount);
verify(mockGateway).processPayment(totalAmount);
}
}
Stub Example:
You want to test how the PaymentProcessor
handles different scenarios, including unsuccessful payments. You use a stub to control the behavior of the processPayment
method:
java
import org.junit.Test;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
public class PaymentProcessorTest {
@Test
public void testProcessOrderWithUnsuccessfulPayment() {
PaymentGateway stubGateway = mock(PaymentGateway.class);
when(stubGateway.processPayment(anyDouble())).thenReturn(false); // Stub behavior
PaymentProcessor processor = new PaymentProcessor(stubGateway);
double totalAmount = 0.0; // Negative amount
assertFalse(processor.processOrder(totalAmount));
verify(stubGateway).processPayment(totalAmount);
}
}
In this example, the when(stubGateway.processPayment(anyDouble())).thenReturn(false)
line sets up the stubbed behavior for the processPayment
method, returning false
for any amount. This allows you to test how the PaymentProcessor
class handles an unsuccessful payment scenario without involving the actual payment processing.
In summary, mocks are used to verify interactions and expectations, while stubs are used to control behavior and isolate code for testing. Both are important tools in unit testing to ensure the correctness of your code.
Comments
Post a Comment