Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mockito cannot mock this class : Mockito can only mock non-private & non-final classes

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

like image 931
CecBazinga Avatar asked Dec 19 '25 10:12

CecBazinga


1 Answers

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.

like image 182
Mick Mnemonic Avatar answered Dec 21 '25 00:12

Mick Mnemonic