Simple Mockito verify works in JUnit but not Spock
Asked Answered
A

2

25

Using the most basic example from Mockito's examples page, I am able to run successfully in JUnit.

However, when I run the same test in Spock, it fails.

JUnit/Java version (this passes):

import org.junit.Test;

import java.util.List;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

public class SimpleJunitTest
{
    @Test
    public void basicMockTest()
    {
        List mockedList = mock(List.class);

        //using mock object
        mockedList.add("one");
        mockedList.clear();

        //verification
        verify(mockedList).add("one");
        verify(mockedList).clear();
    }
}

Spock/Groovy version (this fails):

import static org.mockito.Mockito.mock
import static org.mockito.Mockito.verify


class SimpleSpockTest extends spock.lang.Specification
{
    def "Basic Mock Test"()
    {
        given:
            //mock creation
            List mockedList = mock(List.class);

        when:
            //using mock object
            mockedList.add("one");
            mockedList.clear();

        then:
            //verification
            verify(mockedList).add("one");
            verify(mockedList).clear();
    }

}

Here is the error I get when the Spock Test fails:

Condition not satisfied:

verify(mockedList).add("one")
|      |           |
|      |           false
|      $java.util.List$$EnhancerByMockitoWithCGLIB$$172e393a@613043d2 (renderer threw    
NullPointerException)
$java.util.List$$EnhancerByMockitoWithCGLIB$$172e393a@613043d2 (renderer threw 
NullPointerException)

at SimpleSpockTest.Basic Mock Test(SimpleSpockTest.groovy:25)

Any ideas or suggestions? I really like Spock and Mockito and am hoping to get them working well together. Thank you very much!

Assist answered 21/5, 2013 at 19:38 Comment(0)
S
27

Roughly speaking, a then-block may only contain assertions in the form of boolean expressions. A Mockito verification expression doesn't fit this contract, as it will return a falsy value (null, false, 0) when it passes, which is interpreted as a failed assertion by Spock.

To solve this problem, you can either write a helper method that wraps around the verification expressions and always returns true, or you can use Spock's built-in mocking framework instead of Mockito.

Sg answered 21/5, 2013 at 20:0 Comment(3)
Gotta say, was trying to avoid it, but Spoke's mock verification error messages are pretty freaking awesome.Hoberthobey
Thanks. Great error messages are certainly a trademark of Mockito. Fortunately, I'm regularly getting feedback from Szczepan (creator of Mockito) on how to improve Spock error messages, and most of the time I'm listening to what he says. :-)Sg
I'm coming back to this after a while, since I'm needing to mock some Spring components and still can't do that with Spock mocks, and I've found that Mockito.verify(mock).foo(bar) || true works fine for me and is reasonably readable.Limb
M
4

I have a use case requiring PowerMockito to mock final methods in Java classes (where Spock mocking won't work), but also need to verify they did get called, because the final methods are builder-style and return "this", which makes the tests pass even if the mocked call wasn't called.

My solution was to append "|| true" to my verify calls, like this:

given:
when(myMock.setSomething("xyzzy")).thenReturn(myMock)

when:
def result = objectBeingTested.isExecutedWith("xyzzy")

then:
result == expectedResult
Mockito.verify(myMock).setSomething("xyzzy") || true         // this passes
Mockito.verify(myMock).setSomething("wrongValue") || true    // this FAILS appropriately
Masterwork answered 3/12, 2020 at 17:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.