2
<dependency>
  <groupId>org.powermock</groupId>
  <artifactId>powermock-api-mockito</artifactId>
  <version>1.4.12</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.powermock</groupId>
  <artifactId>powermock-module-junit4</artifactId>
  <version>1.4.12</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.junit.jupiter</groupId>
  <artifactId>junit-jupiter-api</artifactId>
  <version>5.2.0</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.junit.jupiter</groupId>
  <artifactId>junit-jupiter-engine</artifactId>
  <version>5.2.0</version>
  <scope>test</scope>
</dependency>

I am trying to create mock for a singleton enum on java in my scala code, taking reference from here and here. I can not change this singleton as it is coming from some other library, some code of this singleton looks like following:

public enum singleton implements Isingleton {
    INSTANCE;

    public Command getCommand(String name) {  <-- method to be mocked
        ....
    }
   ....
}

Following is some part of code, but I get error:

@RunWith(classOf[PowerMockRunner])
@PrepareForTest(Array(classOf[mySingleTon]))
class myTest  {

  @Test
  def test(): Unit = {
    val mockInstance = org.mockito.Mockito.mock[mySingleTon]  //val mockInstance = org.powermock.api.mockito.PowerMockito.mock(classOf[mySingleTon])
    Whitebox.setInternalState(classOf[mySingleTon], "INSTANCE":String, mockInstance:Any)
    when(mockInstance.getAerospikeCommand(nameCapture.capture())).thenReturn(mockedFunc)

Error is:

org.mockito.exceptions.base.MockitoException: 
Cannot mock/spy class com.my.cap.myModule.Singleton
Mockito cannot mock/spy following:
  - final classes
  - anonymous classes
  - primitive types

    at org.scalatest.mock.MockitoSugar$class.mock(MockitoSugar.scala:74)

I also tried following as suggested here:

@RunWith(classOf[PowerMockRunner])
@PrepareForTest(Array(classOf[mySingleTon]))
class myTest  {

  @Test
  def test(): Unit = {
     import org.powermock.api.mockito.PowerMockito
     PowerMockito.mockStatic(classOf[mySingleTon])
     BDDMockito.given(mySingleTon.INSTANCE.getCommand(nameCapture.capture())).willReturn(mockedCommand)

but than I start to get following error:

java.lang.IllegalArgumentException: Cannot subclass final class class com.cap.myModule.mySingleTon

    at org.mockito.cglib.proxy.Enhancer.generateClass(Enhancer.java:447)
    at org.mockito.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
    at org.mockito.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:217)
    at org.mockito.cglib.proxy.Enhancer.createHelper(Enhancer.java:378)
    at org.mockito.cglib.proxy.Enhancer.createClass(Enhancer.java:318)
Saurabh
  • 71,488
  • 40
  • 181
  • 244
  • You can't mock an enum. More importantly, you _should not_ do it. Mocking is for stubbing out business logic. – Dima Feb 08 '19 at 15:45
  • @Dima In my case, there are some DB call happening from there which I want to mock. There should be some way, and links I referred shows some ways to do it, however not able to replicate those. – Saurabh Feb 08 '19 at 17:20
  • 1
    You not being able to replicate is an indication, that is _not_ really "a way to do it" :) Making db calls from an enum sounds really ... innovative, you did say it wasn't your idea, and you can't change it, but you still have control over whether or how it is actually being used ... One option is to change your code to not use the enum directly. Make a wrapper class, exposing an API interface to callers, that will forward the calls your your unfortunate enum, and then mock _that_. – Dima Feb 08 '19 at 18:39
  • @Dima Thanks for your suggestion, I have updated the code which uses this according to your comment. – Saurabh Feb 12 '19 at 13:30

0 Answers0