1

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

orbfish
  • 7,381
  • 14
  • 58
  • 75
  • 1
    In case you are not aware, Spock comes with out-of-the-box support for spying. – Peter Niederwieser Jun 16 '15 at 19:18
  • Why would anybody use Mockito with Spock? Just use builtin method `Spy(Service)` and done. – topr Jun 25 '15 at 09:45
  • @topr Partly because I'm familiar with Mockito, and I find its syntax clear and concise enough not to stand out in Groovy. But mainly because the homegrown options I've found in Groovy using closures and expandos look difficult to read, and would probably not go over well with my team. I didn't realize there was a Spy construction (is there a Mock?) - I'll take a look, thanks. – orbfish Jun 27 '15 at 20:26
  • Teamm knowing a given till is surely a good argument. However why you go for Spock at then? :) Yes, there is Mock(), Stub() and respectively GroovySpy(), GroovyMock() and GroovyStub() with extended features mostly related to dynamic methods added in runtime. I like Spock for multiple things, one is that it's self-contained. One needs NO additional libs to do proper tests. – topr Jun 29 '15 at 18:46
  • given lib* (time for edition expired) – topr Jun 29 '15 at 18:53
  • Please check this answer http://stackoverflow.com/a/39128168/2381172 – xuesheng Aug 24 '16 at 16:07

2 Answers2

3

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).

Ray
  • 3,084
  • 2
  • 19
  • 27
0

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.

Thalescm
  • 155
  • 1
  • 10