Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Any way to enable Strict Stubbing when using Mockito.mock() without using @Mock? #2648

Closed
sivaprasadreddy opened this issue May 20, 2022 · 4 comments · Fixed by apache/kafka#12460

Comments

@sivaprasadreddy
Copy link
Contributor

Hi,
I am using mockito-core 4.5.1 and JUnit 5. I can use MockitoExtension and @Mock annotation and by default I get Strict Stubbing behaviour. However, if I use Mockito.Mock(MyClass.class) to create mock it seems Strictness is not enabled. Even if I stub unnecessary methods it is not giving any error.

I know I can work around this by using MockitoExtension to create mocks using @mock, but is there any way to enable Strict Stubbing while using Mockito.mock(MyClass.class);

class ProductServiceTest {

    private ProductRepository productRepository;
    private ProductService productService;

    @BeforeEach
    void setUp() {
        productRepository = Mockito.mock(ProductRepository.class);
        productService = new ProductService(productRepository);
        // this is unnecessary method stubbing but it is not giving any error
        Mockito.when(productRepository.findAllActiveProducts()).thenReturn(List.of());
    }

    @Test
    void shouldReturnOnlyActiveProducts() {
        BDDMockito.given(productRepository.findAll()).willReturn(List.of(p1, p2));
        productService.findAll(); // which calls productRepository.findAll()
    }
}
@TimvdLippe
Copy link
Contributor

I would have though that we supported this feature with our MockSettings. While looking that up, I discovered that we do ship lenient(), but we don't ship an equivalent API to set the strictness to STRICT_STUBS. I consider that a deficiency of the API, for which we should add an option. Therefore, +1 to this feature request.

In hindsight, we shouldn't have shipped mockSettings.lenient(), but instead add mockSettings.strictness(Strictness). We have the same issue with @Mock: https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mock.html#lenient()

Therefore, I propose we update both MockSettings and @Mock to accept a new setting called strictness which sets the Strictness. We can then deprecate both lenient() options, as they would be a shortcut for strictness(Strictness.LENIENT).

@sivaprasadreddy Would you like to contribute this feature to Mockito?

@sivaprasadreddy
Copy link
Contributor Author

@TimvdLippe Sure, I will contribute to this feature.

@sivaprasadreddy
Copy link
Contributor Author

@TimvdLippe I have raised a PR #2650 and the GH Actions pipeline is waiting for approval https://github.com/mockito/mockito/actions/runs/2368951973.

@sivaprasadreddy
Copy link
Contributor Author

@TimvdLippe The PR build failed (https://github.com/mockito/mockito/actions/runs/2368951973) because of an error in Javadoc comment, which I have fixed now.

ijuma pushed a commit to apache/kafka that referenced this issue Aug 9, 2022
## Changes
- **mockito: 4.4.0 -> 4.6.1** (https://github.com/mockito/mockito/releases)
Most important updates:
  - Fixes mockito/mockito#2648 : Add support for customising strictness via @mock annotation and MockSettings mockito/mockito#2650

## Why is this change needed?

According to the [Mockito documentation](https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#when(T)) :
> Although it is possible to verify a stubbed invocation, usually it's just redundant. Let's say you've stubbed foo.bar(). If your code cares what foo.bar() returns then something else breaks(often before even verify() gets executed). If your code doesn't care what get(0) returns then it should not be stubbed. 

While working on the [Replace EasyMock and PowerMock with Mockito for StreamsMetricsImplTest ](https://issues.apache.org/jira/browse/KAFKA-12947) I noticed that described behavior wasn't applied when you create a new `mock` like this.

```java
        final Metrics metrics = mock(Metrics.class);
        when(metrics.metric(metricName)).thenReturn(null);

        ... invoke SUT

        verify(metrics).metric(metricName); // this should be redundant (according to docs)

```

After further investigation I figured out that described behaviour wasn't implemented until`v4.6.1`.

With this change we are now able to mock objects like this:

```java
   Foo explicitStrictMock = mock(Foo.class, withSettings().strictness(Strictness.STRICT_STUBS));
```
- link to docs: [MockSettings.html#strictness](https://javadoc.io/static/org.mockito/mockito-core/4.6.1/org/mockito/quality/Strictness.html#STRICT_STUBS)

It looks like I can accomplish the same thing by using the `@RunWith(MockitoJUnitRunner.StrictStubs.class)
` instead of the `@RunWith(MockitoJUnitRunner.class)` so mockito dependency version update is not mandatory, but it would be nice to stay up-to-date and use the latest version (it's up to MR reviewer to decide if we are going to merge this now, or just close the MR and update mockito version later).

Reviewers: Ismael Juma <ismael@juma.me.uk>
a0x8o added a commit to a0x8o/kafka that referenced this issue Aug 9, 2022
## Changes
- **mockito: 4.4.0 -> 4.6.1** (https://github.com/mockito/mockito/releases)
Most important updates:
  - Fixes mockito/mockito#2648 : Add support for customising strictness via @mock annotation and MockSettings mockito/mockito#2650

## Why is this change needed?

According to the [Mockito documentation](https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#when(T)) :
> Although it is possible to verify a stubbed invocation, usually it's just redundant. Let's say you've stubbed foo.bar(). If your code cares what foo.bar() returns then something else breaks(often before even verify() gets executed). If your code doesn't care what get(0) returns then it should not be stubbed.

While working on the [Replace EasyMock and PowerMock with Mockito for StreamsMetricsImplTest ](https://issues.apache.org/jira/browse/KAFKA-12947) I noticed that described behavior wasn't applied when you create a new `mock` like this.

```java
        final Metrics metrics = mock(Metrics.class);
        when(metrics.metric(metricName)).thenReturn(null);

        ... invoke SUT

        verify(metrics).metric(metricName); // this should be redundant (according to docs)

```

After further investigation I figured out that described behaviour wasn't implemented until`v4.6.1`.

With this change we are now able to mock objects like this:

```java
   Foo explicitStrictMock = mock(Foo.class, withSettings().strictness(Strictness.STRICT_STUBS));
```
- link to docs: [MockSettings.html#strictness](https://javadoc.io/static/org.mockito/mockito-core/4.6.1/org/mockito/quality/Strictness.html#STRICT_STUBS)

It looks like I can accomplish the same thing by using the `@RunWith(MockitoJUnitRunner.StrictStubs.class)
` instead of the `@RunWith(MockitoJUnitRunner.class)` so mockito dependency version update is not mandatory, but it would be nice to stay up-to-date and use the latest version (it's up to MR reviewer to decide if we are going to merge this now, or just close the MR and update mockito version later).

Reviewers: Ismael Juma <ismael@juma.me.uk>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants