Home Arrow Icon Knowledge base Arrow Icon Global Arrow Icon Can you provide examples of refactored code that avoids Mockito reset


Can you provide examples of refactored code that avoids Mockito reset


Refactoring code to avoid using Mockito's `reset()` method often involves improving the design of the tests and the code under test. Here are some strategies and examples to help you refactor your code effectively:

1. Avoid Overly Complex Test Scenarios**

Instead of resetting mocks to handle multiple scenarios in a single test, break down your tests into smaller, focused scenarios. This approach ensures that each test has a clear purpose and reduces the need for resetting mocks.

Before:

java
@Test
public void testMultipleScenarios() {
    // Setup mock
    MyService myService = mock(MyService.class);
    when(myService.doSomething()).thenReturn("Result1");
    
    // Test scenario 1
    assertEquals("Result1", myService.doSomething());
    
    // Reset mock for scenario 2
    reset(myService);
    when(myService.doSomething()).thenReturn("Result2");
    
    // Test scenario 2
    assertEquals("Result2", myService.doSomething());
}

After:

java
@Test
public void testScenario1() {
    MyService myService = mock(MyService.class);
    when(myService.doSomething()).thenReturn("Result1");
    assertEquals("Result1", myService.doSomething());
}

@Test
public void testScenario2() {
    MyService myService = mock(MyService.class);
    when(myService.doSomething()).thenReturn("Result2");
    assertEquals("Result2", myService.doSomething());
}

2. Use `clearInvocations()` Instead of `reset()`**

If you need to clear the invocation history of a mock without resetting its stubbing, use `Mockito.clearInvocations()`. This method is useful when you want to verify interactions multiple times in the same test.

java
@Test
public void testClearInvocations() {
    MyService myService = mock(MyService.class);
    when(myService.doSomething()).thenReturn("Result");
    
    // Perform some actions
    myService.doSomething();
    
    // Clear invocations
    clearInvocations(myService);
    
    // Perform more actions
    myService.doSomething();
    
    // Verify interactions
    verify(myService, times(1)).doSomething(); // Only counts the second call
}

3. Refactor Code to Reduce Mocking**

Sometimes, the need for `reset()` arises from overly complex code that requires extensive mocking. Refactor your code to reduce dependencies and make it more testable. For example, instead of mocking a complex object, consider creating a testable wrapper or interface.

Before:

java
public class ComplexService {
    public void doComplexOperation() {
        // Complex logic involving multiple dependencies
    }
}

After:

java
public interface OperationInterface {
    void performOperation();
}

public class ComplexService {
    private final OperationInterface operation;
    
    public ComplexService(OperationInterface operation) {
        this.operation = operation;
    }
    
    public void doComplexOperation() {
        operation.performOperation();
    }
}

In tests, you can then easily mock `OperationInterface` without needing to reset it.

java
@Test
public void testComplexOperation() {
    OperationInterface operation = mock(OperationInterface.class);
    ComplexService service = new ComplexService(operation);
    service.doComplexOperation();
    verify(operation).performOperation();
}

4. Use Strict Stubs**

Using strict stubs can help ensure that your tests fail early if unexpected methods are called, reducing the need for `reset()`. This approach encourages cleaner test code by enforcing that only stubbed methods are called.

java
@Rule
public MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);

@Test
public void testWithStrictStubs() {
    MyService myService = mock(MyService.class);
    when(myService.doSomething()).thenReturn("Result");
    
    // Attempting to call an unstubbed method will throw an exception
    myService.doSomethingElse(); // Throws PotentialStubbingProblem
}

By following these strategies, you can write more focused, maintainable tests that avoid the need for Mockito's `reset()` method.

Citations:
[1] https://www.lambdatest.com/automation-testing-advisor/selenium/methods/org.mockito.Mockito.reset
[2] https://stackoverflow.com/questions/32873928/effects-of-mockito-mocks-on-unit-tests-when-refactoring
[3] https://www.vogella.com/tutorials/Mockito/article.html
[4] https://softwareengineering.stackexchange.com/questions/188299/is-this-an-appropriate-use-of-mockitos-reset-method
[5] https://mestachs.wordpress.com/2012/07/09/mockito-best-practices/
[6] https://www.reddit.com/r/java/comments/wpe5fe/what_is_your_goto_solution_for_resetting_a/
[7] https://reflectoring.io/clean-unit-tests-with-mockito/
[8] https://docs.openrewrite.org/recipes/java/testing/mockito