title: Mockito cannot mock this class : Mockito can only mock non-private & non-final classes
body: <p>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:</p>
  <pre><code>org.mockito.exceptions.base.MockitoException: 
  Mockito cannot mock this class: interface org.apache.bookkeeper.discover.RegistrationManager.
  
  Mockito can only mock non-private &amp; 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.&lt;init&gt;(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.&lt;init&gt;(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
  </code></pre>
  <p>Here the test class i'm writing:</p>
  <pre><code>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&lt;Object[]&gt; 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 ,  &quot;new&quot; },
                  {false , &quot;null&quot; },
                  {false , &quot;wrong&quot;},
                  {false , &quot;mock&quot;},  //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 == &quot;null&quot;){
  
              this.conf = null;
  
          }else if( confType == &quot;wrong&quot;){
  
              this.conf = new ServerConfiguration().setMetadataServiceUri(&quot;zk+hierarchical://127.0.0.1/ledgers&quot;);
  
          }else if(confType == &quot;new&quot;) {
  
              this.conf = new ServerConfiguration(baseConf);
              String ledgersRootPath = &quot;/testledgers&quot;;
              this.conf.setMetadataServiceUri(newMetadataServiceUri(ledgersRootPath));
  
          }else if(confType == &quot;mock&quot;){
  
            
  
              when(mockedRM.initNewCluster()).thenThrow(new Exception());
  
          }
  
  
          try {
  
              realResult = BookKeeperAdmin.initNewCluster(conf);
  
          } catch (Exception e) {
              realResult = false ;
              e.printStackTrace();
  
          }
          assertEquals(result,realResult);
      }
  
  }
  </code></pre>
  <p>And here the interface i'm trying to mock:</p>
  <pre><code>/*
   * 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
   * &quot;License&quot;); 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 &quot;AS IS&quot; 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 &lt;i&gt;bookieId&lt;/i&gt;.
       *
       * @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 &lt;i&gt;bookieId&lt;/i&gt;.
       *
       * @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&lt;byte[]&gt; 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&lt;byte[]&gt; 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;
  }
  </code></pre>
  <p>2 notes:</p>
  <ul>
  <li>i posted also my test class code to be sure there is no conflict in using a parameterized test and mockito</li>
  <li>from what i was able to understand the problem is byteBuddy more than mockito itself but i don't know how to fix this.</li>
  </ul>
  <p>Mockito version i'm using is 3.0.0
  Bytebuddy version is 1.9.3</p>
  <p>I hope you can help me,
  have a good day all :P</p>