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

clearInlineMocks not working with MockitoJUnit.rule() #1902

Open
melihaksoy opened this issue Apr 9, 2020 · 6 comments
Open

clearInlineMocks not working with MockitoJUnit.rule() #1902

melihaksoy opened this issue Apr 9, 2020 · 6 comments

Comments

@melihaksoy
Copy link

melihaksoy commented Apr 9, 2020

Hi !

I recenlty updated to 2.25.0 to make use of clearInlineMocks but I end up with NotAMockException when I use it in combination with MockitoJUnit.rule().

Eg

class ExampleUnitTest {

    @get:Rule
    val mockitoRule: MockitoRule = MockitoJUnit.rule()

    @Mock
    lateinit var state: MainState

    @After
    fun clearMocks() {
        Mockito.framework().clearInlineMocks()
    }

    @Test
    fun randomTest() {
		state.something
		Mockito.verify(state).something
    }
}

ends up with

org.mockito.exceptions.misusing.NotAMockException: Argument passed to Mockito.mockingDetails() should be a mock, but is an instance of class com.melih.playground.ui.main.state.MainState!

	at org.mockito.internal.junit.JUnitRule$1.evaluate(JUnitRule.java:49)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
	at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
	at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)

and tests fail.

If I use @RunWith(MockitoJUnitRunner::class) tests pass, but I still get same exception at end of run.

If I remove rule & use MockitoAnnotations.initMocks(this) everything works fine.

@melihaksoy melihaksoy changed the title clearInlineMocks not working with MockitoJUnit rule clearInlineMocks not working with MockitoJUnit.rule() Apr 9, 2020
@TimvdLippe
Copy link
Contributor

clearInlineMocks (and all Mockito.framework() APIs) are not intended to be used in regular tests. Instead, they are exposed for those frameworks who want to integrate with Mockito (think of Spring Boot for example). What made you want to choose this API?

Also, it seems like you are using Kotlin. Could it be that the Rule doesn't work correctly when used in combination with Kotlin?

@melihaksoy
Copy link
Author

melihaksoy commented Apr 14, 2020

From what's new for 2.25.0 & issue 1614 it sounds like something we should use to prevent mockito-inline from leaking, and we're using it in all modules so far.

MockitoJUnit.rule() worked without any problems, we didn't encounter any anything until we added inline mock clearing.

So clearInlineMocks is not for @After of tests with mockito-inline of my Kotlin tests ?

@TimvdLippe
Copy link
Contributor

Could you open a PR with a reproduction test case? Then I can take a look.

@melihaksoy
Copy link
Author

Sorry for late response !

Code piece in question is from a fresh project, just added mockito & rule to ExampleUnitTest, nothing else.

@ttanxu
Copy link
Contributor

ttanxu commented Nov 14, 2020

I have a theory, but I didn't verify that explicitly so I might be wrong. Just to put this theory here to guide folks to a possible solution.

JUnit runs @Before after each rule, and @After before each rule. In this particular case clearInlineMocks() removed internal handlers of all inline mocks, but MockitoJUnit rule still needs to use them which made this exception.

The solution is to wrap clearInlineMocks() in a TestRule as well, and use RuleChain to make sure the order of those 2 rules.

I'll leave it to Mockito team to decide if it should offer more guidance around the use of clearInlineMocks(), or even encapsulate the use of it into MockitoJUnit rule.

@ZacSweers
Copy link

ZacSweers commented Nov 18, 2020

Wow, currently experiencing this XKCD comic. Thank you @ttanxu, that resolved our issue.

Worth noting that RuleChain for ordering is discouraged in Junit 4.13+, so using Rule's ordering works instead

// Use Mockito's new strict stubs listener, which fails early on mismatched types.
// This also handles validating mocks and closing them after the test to prevent leaks.
@Rule(order = 0)
@JvmField
val mockitoRule: MockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS)

// This needs to run _after_ mockitoRule is done
// https://github.com/mockito/mockito/issues/1902#issuecomment-727093806
@Rule(order = 1)
@JvmField
internal val clearInlineMocksRule: TestRule = ClearInlineMocksRule()

sb-yb added a commit to yugabyte/yugabyte-db that referenced this issue Nov 28, 2022
Summary:
This change reverts commit d7afbc6
This also fixes the OOM caused by mockito memory leak:
See: mockito/mockito#1614
The mockito internal map was using 95% of the memory at the time of the OOM.

As suggested we are now calling
```
    Mockito.framework().clearInlineMocks()
```

However we are calling only once per class instead of after each test method.
This is because it interfears with JunitMockito rule.
Alternative is to add rull ordering as suggested in:
mockito/mockito#1902 (comment)

Test Plan: This fixes the tests

Reviewers: yshchetinin, hzare

Reviewed By: yshchetinin, hzare

Subscribers: yshchetinin, jenkins-bot, yugaware

Differential Revision: https://phabricator.dev.yugabyte.com/D21333
jayant07-yb pushed a commit to jayant07-yb/yugabyte-db that referenced this issue Dec 7, 2022
Summary:
This change reverts commit d7afbc6
This also fixes the OOM caused by mockito memory leak:
See: mockito/mockito#1614
The mockito internal map was using 95% of the memory at the time of the OOM.

As suggested we are now calling
```
    Mockito.framework().clearInlineMocks()
```

However we are calling only once per class instead of after each test method.
This is because it interfears with JunitMockito rule.
Alternative is to add rull ordering as suggested in:
mockito/mockito#1902 (comment)

Test Plan: This fixes the tests

Reviewers: yshchetinin, hzare

Reviewed By: yshchetinin, hzare

Subscribers: yshchetinin, jenkins-bot, yugaware

Differential Revision: https://phabricator.dev.yugabyte.com/D21333
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants