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

Different mocks are used for @Mock and @InjectMock in the same test class with JUnit 5 extension #1346

Closed
szpak opened this Issue Mar 25, 2018 · 10 comments

Comments

Projects
None yet
3 participants
@szpak
Member

szpak commented Mar 25, 2018

I've been playing with the new JUnit 5 support in Mockito 2.17.0. I have found that with @Mock and @InjectMocks used in the same test class different mocks are injected. I would expect to have the same mock reused (as it works with JUnit 4 or manual @Mock initialization).

Sample code:

@ExtendWith(MockitoExtension.class)
public class SpaceShip5BugMiniTest {

    @InjectMocks
    private SpaceShip spaceShip;

    @Mock
    private TacticalStation tacticalStation;

    @Test
    public void shouldInjectMocks() {
        assertThat(tacticalStation).isNotNull();
        assertThat(spaceShip.getTacticalStation()).isEqualTo(tacticalStation);  
        //Bug ↑ - different mocks are use in @Mock and @InjectMock
    }
}

Error message:

org.opentest4j.AssertionFailedError: 
Expecting:
 <"tacticalStation (TacticalStation$MockitoMock$991606095@61d6015a)">
to be equal to:
 <"tacticalStation (TacticalStation$MockitoMock$991606095@b62d79)">
but was not.
Expected :tacticalStation
Actual   :tacticalStation

The minimal (non-)working example is available here.

@TimvdLippe Do you have an idea what could be wrong?

Mockito 2.17.0 (2.17.1 is not being released due to (mockito/shipkit#679), junit-jupiter 5.1.0, OpenJDK 1.8.0_161, Linux.

Checklist:

  • The mockito message in the stacktrace have useful information, but it didn't help
  • The problematic code (if that's possible) is copied here;
    Note that some configuration are impossible to mock via Mockito
  • Provide versions (mockito / jdk / os / any other relevant information)
  • Provide a Short, Self Contained, Correct (Compilable), Example of the issue
    (same as any question on stackoverflow.com)
  • Read the contributing guide

@szpak szpak added the bug label Mar 25, 2018

@TimvdLippe

This comment has been minimized.

Contributor

TimvdLippe commented Mar 25, 2018

Hm that seems really weird. Could you please post the implementation of TacticalStation and SpaceShip (although I am assuming they are simple POJO's?)

@TimvdLippe

This comment has been minimized.

Contributor

TimvdLippe commented Mar 25, 2018

@TimvdLippe

This comment has been minimized.

Contributor

TimvdLippe commented Mar 25, 2018

@szpak Please see https://github.com/mockito/mockito/blob/5e9a3c62fc1ca4cf12d5d19580613f418cebc895/subprojects/junit-jupiter/src/test/java/org/mockitousage/InjectMocksTest.java for a working test. I could make these tests fail with adding final to the field declaration, so that is what is going wrong. Removing final makes the tests pass.

What I do not understand is how this could work with JUnit 4, as we have not changed any of that code. We are completely reusing all of that logic.

@szpak

This comment has been minimized.

Member

szpak commented Mar 25, 2018

It also works with final if MockitoAnnotations.initMocks(this); is used. Therefore, I would suspect the way how it is triggered/executed in JUnit 5 extension.

@SeriyBg

This comment has been minimized.

Contributor

SeriyBg commented Mar 26, 2018

@TimvdLippe @szpak I have debugged this issue a bit. Here is what I found: it does look like the problem is with triggering the same logic from MockitoExtension.class.
The root cause of the problem is that beforeEach creates two testInstances of the same test class for each test.
Looks like method collectParentTestInstances is adding the same testInstance to the list of test instances.
I can try to work on this issue if no one is assigned to is already.

@TimvdLippe

This comment has been minimized.

Contributor

TimvdLippe commented Mar 26, 2018

@SeriyBg

This comment has been minimized.

Contributor

SeriyBg commented Mar 26, 2018

Have added PR #1349 with the fix for the issue

SeriyBg added a commit to SeriyBg/mockito that referenced this issue Mar 26, 2018

Fix mockito#1346 - Different mocks are used for @mock and @InjectMock…
… in the same test class with JUnit 5 extension

TimvdLippe added a commit that referenced this issue Mar 26, 2018

@szpak

This comment has been minimized.

Member

szpak commented Mar 27, 2018

It works flawlessly. Thanks @SeriyBg!

@TimvdLippe As this bug can impact all those people preferring a constructor injection, what do you thing about releasing the new minor version (e.g. after #1350 is hopefully merged :) ) to Maven Central?

@TimvdLippe

This comment has been minimized.

Contributor

TimvdLippe commented Mar 27, 2018

@szpak Yes after #1350 we will probably publish a new version. You can however already use the latest version from Bintray

@szpak

This comment has been minimized.

Member

szpak commented Mar 27, 2018

I know Tim that I can, but JUnit 5 support is a notable feature and having it working correctly in the latest non-development version (available in Maven Central) seems very sensible for me. Great, that we agree on releasing a new stable (but IHMO still 2.17.x) version soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment