3

For a university exam i was given to test some of apache bookkeeper classes/methods and in doing so i thought to use mockito in my parameterized test. Test without mockito works fine but when i try to mock an interface i get this error:

org.mockito.exceptions.base.MockitoException: Mockito cannot mock this class: interface org.apache.bookkeeper.discover.RegistrationManager. Mockito can only mock non-private & non-final classes. If you're not sure why you're getting this error, please report to the mailing list. Java : 11 JVM vendor name : Ubuntu JVM vendor version : 11.0.8+10-post-Ubuntu-0ubuntu118.04.1 JVM name : OpenJDK 64-Bit Server VM JVM version : 11.0.8+10-post-Ubuntu-0ubuntu118.04.1 JVM info : mixed mode, sharing OS name : Linux OS version : 4.15.0-112-generic Underlying exception : java.lang.IllegalArgumentException: Could not create type at org.apache.bookkeeper.client.BookKeeperAdminInitNewClusterTest.<init>(BookKeeperAdminInitNewClusterTest.java:40) at org.junit.runners.parameterized.BlockJUnit4ClassRunnerWithParameters.createTestUsingConstructorInjection(BlockJUnit4ClassRunnerWithParameters.java:43) at org.junit.runners.parameterized.BlockJUnit4ClassRunnerWithParameters.createTest(BlockJUnit4ClassRunnerWithParameters.java:38) at org.junit.runners.BlockJUnit4ClassRunner$1.runReflectiveCall(BlockJUnit4ClassRunner.java:266) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:263) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.junit.runners.Suite.runChild(Suite.java:128) at org.junit.runners.Suite.runChild(Suite.java:27) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69) at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33) at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220) at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53) Caused by: java.lang.IllegalArgumentException: Could not create type at net.bytebuddy.TypeCache.findOrInsert(TypeCache.java:154) at net.bytebuddy.TypeCache$WithInlineExpunction.findOrInsert(TypeCache.java:365) at net.bytebuddy.TypeCache.findOrInsert(TypeCache.java:174) at net.bytebuddy.TypeCache$WithInlineExpunction.findOrInsert(TypeCache.java:376) at org.mockito.internal.creation.bytebuddy.TypeCachingBytecodeGenerator.mockClass(TypeCachingBytecodeGenerator.java:32) at org.mockito.internal.creation.bytebuddy.SubclassByteBuddyMockMaker.createMockType(SubclassByteBuddyMockMaker.java:71) at org.mockito.internal.creation.bytebuddy.SubclassByteBuddyMockMaker.createMock(SubclassByteBuddyMockMaker.java:42) at org.mockito.internal.creation.bytebuddy.ByteBuddyMockMaker.createMock(ByteBuddyMockMaker.java:25) at org.powermock.api.mockito.mockmaker.PowerMockMaker.createMock(PowerMockMaker.java:41) at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:35) at org.mockito.internal.MockitoCore.mock(MockitoCore.java:62) at org.mockito.Mockito.mock(Mockito.java:1908) at org.mockito.Mockito.mock(Mockito.java:1817) at org.apache.bookkeeper.client.BookKeeperAdminInitNewClusterTest.<init>(BookKeeperAdminInitNewClusterTest.java:40) at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490) ... 26 more Caused by: java.lang.NoSuchMethodError: 'net.bytebuddy.dynamic.loading.MultipleParentClassLoader$Builder net.bytebuddy.dynamic.loading.MultipleParentClassLoader$Builder.appendMostSpecific(java.util.Collection)' at org.mockito.internal.creation.bytebuddy.SubclassBytecodeGenerator.mockClass(SubclassBytecodeGenerator.java:83) at org.mockito.internal.creation.bytebuddy.TypeCachingBytecodeGenerator$1.call(TypeCachingBytecodeGenerator.java:37) at org.mockito.internal.creation.bytebuddy.TypeCachingBytecodeGenerator$1.call(TypeCachingBytecodeGenerator.java:34) at net.bytebuddy.TypeCache.findOrInsert(TypeCache.java:152) ... 43 more 

Here the test class i'm writing:

package org.apache.bookkeeper.client; import org.apache.bookkeeper.conf.ServerConfiguration; import org.apache.bookkeeper.discover.RegistrationManager; import org.apache.bookkeeper.discover.ZKRegistrationManager; import org.apache.bookkeeper.meta.LayoutManager; import org.apache.bookkeeper.test.BookKeeperClusterTestCase; import org.apache.bookkeeper.test.ZooKeeperCluster; import org.apache.bookkeeper.test.ZooKeeperUtil; import org.apache.zookeeper.ZooKeeper; import org.apache.zookeeper.data.ACL; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.mockito.InjectMocks; import org.mockito.Mock; import java.util.Arrays; import java.util.Collection; import java.util.List; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @RunWith(value= Parameterized.class) public class BookKeeperAdminInitNewClusterTest extends BookKeeperClusterTestCase { private boolean result; private ServerConfiguration conf; private String confType ; private static final int numOfBookies = 2; private final int lostBookieRecoveryDelayInitValue = 1800; @Mock RegistrationManager mockedRM = mock(RegistrationManager.class) ; @Parameterized.Parameters public static Collection<Object[]> getTestParameters(){ return Arrays.asList(new Object[][]{ //last parameter states if the method rm.initNewCluster() called inside // BookKeeperAdmin.initNewCluster(conf) must be mocked or not {true , "new" }, {false , "null" }, {false , "wrong"}, {false , "mock"}, //caso di test introdotto per portare la branch coverage al 100% // entrando nella clausola catch del metodo initNewCluste() }); } public BookKeeperAdminInitNewClusterTest(boolean result , String conf) throws Exception { super(numOfBookies, 480); baseConf.setLostBookieRecoveryDelay(lostBookieRecoveryDelayInitValue); baseConf.setOpenLedgerRereplicationGracePeriod(String.valueOf(30000)); setAutoRecoveryEnabled(true); this.result = result; this.confType = conf; } @Test public void testInitNewCluster() throws Exception { boolean realResult ; if(confType == "null"){ this.conf = null; }else if( confType == "wrong"){ this.conf = new ServerConfiguration().setMetadataServiceUri("zk+hierarchical://127.0.0.1/ledgers"); }else if(confType == "new") { this.conf = new ServerConfiguration(baseConf); String ledgersRootPath = "/testledgers"; this.conf.setMetadataServiceUri(newMetadataServiceUri(ledgersRootPath)); }else if(confType == "mock"){ when(mockedRM.initNewCluster()).thenThrow(new Exception()); } try { realResult = BookKeeperAdmin.initNewCluster(conf); } catch (Exception e) { realResult = false ; e.printStackTrace(); } assertEquals(result,realResult); } } 

And here the interface i'm trying to mock:

/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.bookkeeper.discover; import org.apache.bookkeeper.bookie.BookieException; import org.apache.bookkeeper.common.annotation.InterfaceAudience.LimitedPrivate; import org.apache.bookkeeper.common.annotation.InterfaceStability.Evolving; import org.apache.bookkeeper.versioning.Version; import org.apache.bookkeeper.versioning.Versioned; /** * Registration manager interface, which a bookie server will use to do the registration process. */ @LimitedPrivate @Evolving public interface RegistrationManager extends AutoCloseable { /** * Registration Listener on listening the registration state. */ @FunctionalInterface interface RegistrationListener { /** * Signal when registration is expired. */ void onRegistrationExpired(); } @Override void close(); /** * Return the cluster instance id. * * @return the cluster instance id. */ String getClusterInstanceId() throws BookieException; /** * Registering the bookie server as <i>bookieId</i>. * * @param bookieId bookie id * @param readOnly whether to register it as writable or readonly * @param serviceInfo information about services exposed by the Bookie * @throws BookieException when fail to register a bookie. */ void registerBookie(String bookieId, boolean readOnly, BookieServiceInfo serviceInfo) throws BookieException; /** * Unregistering the bookie server as <i>bookieId</i>. * * @param bookieId bookie id * @param readOnly whether to register it as writable or readonly * @throws BookieException when fail to unregister a bookie. */ void unregisterBookie(String bookieId, boolean readOnly) throws BookieException; /** * Checks if Bookie with the given BookieId is registered as readwrite or * readonly bookie. * * @param bookieId bookie id * @return returns true if a bookie with bookieid is currently registered as * readwrite or readonly bookie. * @throws BookieException */ boolean isBookieRegistered(String bookieId) throws BookieException; /** * Write the cookie data, which will be used for verifying the integrity of the bookie environment. * * @param bookieId bookie id * @param cookieData cookie data * @throws BookieException when fail to write cookie */ void writeCookie(String bookieId, Versioned<byte[]> cookieData) throws BookieException; /** * Read the cookie data, which will be used for verifying the integrity of the bookie environment. * * @param bookieId bookie id * @return versioned cookie data * @throws BookieException when fail to read cookie */ Versioned<byte[]> readCookie(String bookieId) throws BookieException; /** * Remove the cookie data. * * @param bookieId bookie id * @param version version of the cookie data * @throws BookieException when fail to remove cookie */ void removeCookie(String bookieId, Version version) throws BookieException; /** * Prepare ledgers root node, availableNode, readonly node.. * * @return Returns true if old data exists, false if not. */ boolean prepareFormat() throws Exception; /** * Initializes new cluster by creating required znodes for the cluster. If * ledgersrootpath is already existing then it will error out. * * @return returns true if new cluster is successfully created or false if it failed to initialize. * @throws Exception */ boolean initNewCluster() throws Exception; /** * Do format boolean. * * @return Returns true if success do format, false if not. */ boolean format() throws Exception; /** * Nukes existing cluster metadata. * * @return returns true if cluster metadata is successfully nuked * or false if it failed to nuke the cluster metadata. * @throws Exception */ boolean nukeExistingCluster() throws Exception; } 

2 notes:

  • i posted also my test class code to be sure there is no conflict in using a parameterized test and mockito
  • from what i was able to understand the problem is byteBuddy more than mockito itself but i don't know how to fix this.

Mockito version i'm using is 3.0.0 Bytebuddy version is 1.9.3

I hope you can help me, have a good day all :P

1 Answer 1

3

Looking at this bug report, you might have a version incompatibility problem with ByteBuddy and Mockito.

Try to either downgrade Mockito to version 2.23 or upgrade ByteBuddy to version 1.97.

Sign up to request clarification or add additional context in comments.

5 Comments

Sorry for the dumb question but how can i downgrade mockito to version 2.23? I tried to set it in pom.xml and removing the library dependencies in my modules structure but when i try to use mockito intellij tells me to add the maven dependency to Mockito-core-3.0.Sorry if it's a dumb question but it' s a big project i have imported so it's bit difficult to me understand how to handle it!
Might be that the newer version is coming from some other POM or from cache. In IntelliJ, you could try invalidating the IDE's caches (File->Invalidate caches) and also reimporting all Maven projects from Maven settings.
Ty sir i try and post you an update! In the meanwhile ty for your time/kindness.
Great man cleaning cache was the solution! Ty very much. Can i ask you, if you know, why if i mock an interface it's implementation it's not mocked too? Ty for your great help!
Nice to hear that you got it working. I'm not sure what you mean with that question exactly. Anything that you mock with mock() will essentially become an "empty implementation" of the target interface/class (meaning that the methods don't do anything and only return primitive default values or nulls for any object return values). You then need to provide the needed (mocked) implementation yourself using Mockito's doReturn(...).when(...) construct. Maybe you could ask another question if you're having difficulties working with mocks?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.