Cannot Mockito spy class in Spock test?

8.7k Views Asked by At

I'm trying to spy a Java class in a Spock test. I've not had a problem with Mockito in Spock/Groovy before.

When I try to do the following:

def service = spy(Service.class)

I get the following error:

org.mockito.exceptions.base.MockitoException: 
Cannot mock/spy class java.lang.Class
Mockito cannot mock/spy following:
  - final classes
  - anonymous classes
  - primitive types

When I do mock(Service.class) though, it works fine.

I have confirmed that the class is not final, anonymous, or primitive.

Any ideas? I have a random generator in the class (ak) so I need to spy not mock.

Thank you

2

There are 2 best solutions below

0
On BEST ANSWER

Mockito doesn't spy on Classes (or Mocks), it spies on (regular) Objects. Thus, instead of

def service = spy(Service.class)

you have to write

def service = spy(new Service())

(or whichever constructor is appropriate for your scenario).

0
On

Just an extra to Ray's answer, you can also spy on already created instances. The only thing is that all methods you called before spy() was called, cannot be verified. Like:

ClassToSpy spiedInstance;

@Before
public void before () {
    spiedInstance = new ClassToSpy();
}

@Test
public void testWillFail() {
    spiedInstance.method();
    spiedInstance = spy(spiedInstance);

    verify(spiedInstance).method();
}

@Test
public void testWillPass() {
    spiedInstance = spy(spiedInstance);
    spiedInstance.method();

    verify(spiedInstance).method();
}

The error you would get from testWillFail would be similar to:

Wanted but not invoked:
classToSpy.method();
-> at your.package.testWillFail(TestClass.java:line)
Actually, there were zero interactions with this mock.

Due to the fact that, after spied, you did not call this method.