Skip to content

RemoveInitMocksIfRunnersSpecified changes Mockito strictness by removing openMocks #987

@protocol7

Description

@protocol7

What version of OpenRewrite are you using?

  • rewrite-testing-frameworks: 3.35.2
  • rewrite-core: 8.81.1
  • rewrite-java: 8.81.1

What is the smallest, simplest way to reproduce the problem?

import static org.mockito.Mockito.when;

import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
class ExampleTest {
  @Mock List<String> list;

  @BeforeEach
  void setUp() {
    MockitoAnnotations.openMocks(this);
    when(list.size()).thenReturn(1);
  }

  @Test
  void test() {}
}

Run org.openrewrite.java.testing.mockito.RemoveInitMocksIfRunnersSpecified.

What did you expect to see?

If the recipe is intended to be semantics-preserving, MockitoAnnotations.openMocks(this) should be preserved in this case, or the recipe should otherwise preserve the effective Mockito strictness.

Although the call looks redundant with @ExtendWith(MockitoExtension.class), removing it is not behaviorally equivalent here. The extension initializes mocks before @BeforeEach; the explicit openMocks(this) call then replaces the field with a mock that is not owned by the extension's strict session.

What did you see instead?

The recipe removes MockitoAnnotations.openMocks(this):

import static org.mockito.Mockito.when;

import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
class ExampleTest {
  @Mock List<String> list;

  @BeforeEach
  void setUp() {
    when(list.size()).thenReturn(1);
  }

  @Test
  void test() {}
}

This changes test behavior. The unused stubbing is now attached to the Mockito extension-managed mock, so the test can fail with UnnecessaryStubbingException.

If this strictness change is intentional for the recipe, then this is expected behavior and consumers need to opt out of the recipe. But the current recipe description says these calls are redundant, while this case is not behaviorally redundant.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions