Mockito throwing UnfinishedVerificationException (possibly associated with calling a native method)

I have the following exception when I run a test case:

org.mockito.exceptions.misusing.UnfinishedVerificationException: Missing method call for verify(mock) here: -> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) Example of correct verification: verify(mock).doSomething() Also, this error might show up because you verify either of: final/private/equals()/hashCode() methods. Those methods *cannot* be stubbed/verified. at com.bignibouX.tests.repository.member.MemberCachingIntegrationTest.testFindByEmail(MemberCachingIntegrationTest.java:61) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:72) at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:81) at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:215) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:81) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:60) at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:67) at org.junit.runners.ParentRunner.run(ParentRunner.java:309) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:161) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 

In the test example, two tests:

 @ActiveProfiles(Profiles.TEST) @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = { FullIntegrationTestConfiguration.class, BaseTestConfiguration.class, MemberCachingIntegrationTest.Config.class }) public class MemberCachingIntegrationTest { private static final Member MEMBER_ONE = new Member(); private static final Member MEMBER_TWO = new Member(); @Autowired private MemberRepository memberRepositoryMock; @After public void validate() { validateMockitoUsage(); } @Test public void testFindByEmail() { when(memberRepositoryMock.findByEmail(anyString())).thenReturn(MEMBER_ONE, MEMBER_TWO); Member firstInvocation = memberRepositoryMock.findByEmail(" foo@foo.com "); assertThat(firstInvocation, is(MEMBER_ONE)); Member secondInvocation = memberRepositoryMock.findByEmail(" foo@foo.com "); assertThat(secondInvocation, is(MEMBER_ONE)); verify(memberRepositoryMock, times(1)).findByEmail(" foo@foo.com "); Member thirdInvocation = memberRepositoryMock.findByEmail(" bar@bar.com "); assertThat(thirdInvocation, is(MEMBER_TWO)); verify(memberRepositoryMock, times(1)).findByEmail(" bar@bar.com "); } @Test public void passingInexistentEmailToSendPasswordResetShouldNotCauseNPE() { fail("MemberRepository findByEmail throws NPE if email not found in db! Reason: because cache was set up not to allow null values..."); fail("Appropriate error page not displayed when above NPE is thrown!"); } @Profile(Profiles.TEST) @Configuration static class Config { @Bean public MemberRepository memberRepositoryMock() { return mock(MemberRepository.class); } } } 

My question is twofold:

  • I'm not sure what is being called here: sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ... This is due to reflection and a native method, but what is the native method in my case?
  • What am I wrong with my use of Mockito?

change

 @RooJpaRepository(domainType = Member.class) public interface MemberRepository { @Cacheable(value = CacheConfiguration.DATABASE_CACHE_NAME) Member findByEmail(String email); @Cacheable(CacheConfiguration.DATABASE_CACHE_NAME) Member findByToken(String token); @CacheEvict(value = CacheConfiguration.DATABASE_CACHE_NAME, key = "#result.email") <S extends Member> S save(S entity); } 

change 2 :

I debugged the test and turned on screen capture, which seems to confirm what macias said:

output from debug

 org.springframework.aop.framework.ProxyFactory: 2 interfaces [com.bignibou.repository.member.MemberRepository, org.mockito.cglib.proxy.Factory]; 1 advisors [org.springframework.cache.interceptor.BeanFactoryCacheOperationSourceAdvisor: advice bean 'null']; targetSource [SingletonTargetSource for target object [com.bignibou.repositor y.member.MemberRepository$$EnhancerByMockitoWithCGLIB$$1b543cbe@ 4cca9ed4]]; proxyTargetClass=false; optimize=false; opaque=false; exposeProxy=false; frozen=false 

edit 3 . Another thing to consider: if I delete or comment out both the last line in the test, and the breakdown method, i.e.

 verify(memberRepositoryMock, times(1)).findByEmail(" bar@bar.com "); 

and

 @After public void validate() { validateMockitoUsage(); } 

The test passes without problems ....

edit 4 . I am really trying desperately to adapt the following example: https://stackoverflow.com/a/166185/ which was provided to me in another post. It should be noted that the layout is auto-notified, and the test uses the spring context. Can someone please help me get my test right?

+6
source share
1 answer

sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) - according to the stack trace you provided, mockito got a little confused when reporting an error. This is not related to your problem, but in any case NativeMethodAccessorImpl.invoke0 , which is native (see grep code ). SpringJUnit4ClassRunner launches it, how it works, you do not need anything.

Now about your real problem, as I wrote in the comment, this is because Spring wraps the object layout in a proxy. If you add

 System.out.println(memberRepositoryMock.getClass()); 

You will see in the console that this is not a layout, but some kind of proxy server. Mockito can only drown out ridicule, so you get an error.

Now the question may arise how to do this. First, your test is not really an integration test, because you are trying to make fun of the repository, and not really check how the data access behaves. In this case, I would give up using spring -test and just switch to a simple MockitoJUnitRunner.

UPDATE:

OK, now, knowing that this is actually a cache server, I understand that you need your repository to be decorated with a Spring cache, and that your IS test really be an integration test.

Here's how to do it. A slight variation of the mentioned frant.hartm sentence, but without using a static link. A little more natural I think.

 @ActiveProfiles(Profiles.TEST) @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = { FullIntegrationTestConfiguration.class, BaseTestConfiguration.class, MemberCachingIntegrationTest.Config.class }) public class MemberCachingIntegrationTest { @Autowired private MemberRepository cachedRepository; @Autowired private MockProvider mockProvider; @After public void validate() { validateMockitoUsage(); } @Test public void test() { when(mockProvider.get().findByEmail(anyString())).thenReturn("foo", "bar"); String firstInvocation = cachedRepository.findByEmail(" foo@foo.com "); assertThat(firstInvocation, is("foo")); String secondInvocation = cachedRepository.findByEmail(" foo@foo.com "); assertThat(secondInvocation, is("foo")); verify(mockProvider.get(), times(1)).findByEmail(" foo@foo.com "); String thirdInvocation = cachedRepository.findByEmail(" bar@bar.com "); assertThat(thirdInvocation, is("bar")); verify(mockProvider.get(), times(1)).findByEmail(" bar@bar.com "); } @Configuration static class Config { private MemberRepository mockRepository = mock(MemberRepository.class); @Bean public MemberRepository cachedRepository() { return mockRepository; } @Bean public MockProvider mockProvider() { return new MockProvider(mockRepository); } } public static class MockProvider { private final MemberRepository repository; public MockProvider(MemberRepository repository) { this.repository = repository; } public MemberRepository get() { return this.repository; } } } 

Note. Repository returns rows instead of members for a clearer example

+6
source

Source: https://habr.com/ru/post/971460/


All Articles