1

Exception appear when I try to capture more than one value using EasyMock.

easymock 2.5.2
easymockclassextension 2.2
mockito-all 1.8.5
hamcrest-all 1.1

How to solve it using EasyMock ?

Initial code:

package easymock;

public class User {
    public static final int INT_VALUE = 1;
    public static final boolean BOOLEAN_VALUE = false;
    public static final String STRING_VALUE = "";
    private Service service;

    public void setService(Service service) {
        this.service = service;
    }

    public String userMethod(){
        return service.doSomething(INT_VALUE, BOOLEAN_VALUE, STRING_VALUE);
    }
}


package easymock;

public class Service {
    public String doSomething(Integer a, boolean b, String c){
        return null;
    }
}


package easymock;

import org.easymock.Capture;
import org.easymock.classextension.EasyMock;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;

import static org.easymock.EasyMock.anyBoolean;
import static org.easymock.EasyMock.anyObject;
import static org.easymock.classextension.EasyMock.capture;
import static org.easymock.classextension.EasyMock.expect;
import static org.easymock.classextension.EasyMock.replay;
import static org.easymock.classextension.EasyMock.verify;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class UserTest {

    private User user;
    private Service easyMockNiceMock;
    private Service mockitoMock;

    @Before
    public void setUp() throws Exception {
        user = new User();
        easyMockNiceMock = EasyMock.createNiceMock(Service.class);
        mockitoMock = mock(Service.class);
    }

    @Test
    public void easyMockTest() throws Exception {
        // given
        user.setService(easyMockNiceMock);

        Capture<Integer> integerCapture = new Capture<Integer>();
        Capture<Boolean> booleanCapture = new Capture<Boolean>();
        Capture<String> stringCapture = new Capture<String>();
        expect(easyMockNiceMock.doSomething(capture(integerCapture), capture(booleanCapture), capture(stringCapture))).andReturn("");
        replay(easyMockNiceMock);
        // when
        user.userMethod();
        // then
        verify(easyMockNiceMock);
        assertThat(integerCapture.getValue(), is(User.INT_VALUE));
        assertThat(booleanCapture.getValue(), is(User.BOOLEAN_VALUE));
        assertThat(stringCapture.getValue(), is(User.STRING_VALUE));
    }

    @Test
    public void easyMockTestValid() throws Exception {
        // given
        user.setService(easyMockNiceMock);

        Capture<Integer> integerCapture = new Capture<Integer>();
        expect(easyMockNiceMock.doSomething(capture(integerCapture), anyBoolean(), (String) anyObject())).andReturn("");
        replay(easyMockNiceMock);
        // when
        user.userMethod();
        // then
        verify(easyMockNiceMock);
        assertThat(integerCapture.getValue(), is(User.INT_VALUE));
    }

    @Test
    public void mockitoTest() throws Exception {
        // given
        user.setService(mockitoMock);

        ArgumentCaptor<Integer> integerArgumentCaptor = ArgumentCaptor.forClass(Integer.class);
        ArgumentCaptor<Boolean> booleanArgumentCaptor = ArgumentCaptor.forClass(Boolean.class);
        ArgumentCaptor<String> stringArgumentCaptor = ArgumentCaptor.forClass(String.class);

        when(mockitoMock.doSomething(integerArgumentCaptor.capture(), booleanArgumentCaptor.capture(), stringArgumentCaptor.capture())).thenReturn("");
        // when
        user.userMethod();
        // then
        assertThat(integerArgumentCaptor.getValue(), is(User.INT_VALUE));
        assertThat(booleanArgumentCaptor.getValue(), is(User.BOOLEAN_VALUE));
        assertThat(stringArgumentCaptor.getValue(), is(User.STRING_VALUE));
    }
}

Test results:

  1. mockitoTest - always pass
  2. easyMockTestValid - pass if it's run without easyMockTest
  3. easyMockTest - always fail with message:


java.lang.NullPointerException
        at easymock.UserTest.easyMockTest(UserTest.java:41)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
        at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
        at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
        at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
        at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
        at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
        at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
        at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:71)
        at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:202)
        at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:63)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Rrr
  • 1,747
  • 3
  • 17
  • 22

1 Answers1

2

First you are using different versions of EasyMock and EasyMock class extensions. I don't think the issue in your case, though I would rather advise you to have coherent versions.

Secondly, I tried your code with version 3.1 of EasyMock, where the class extension is no longer needed, and the tests passed. I didn't see anything interesting in the changelog, though, Henri might changed something in the code that made your code working.

Hope that helps.

bric3
  • 40,072
  • 9
  • 91
  • 111
  • There is no problem with different versions of EM and classextension. Bug was in easymock 2.5 itself. In 3.1 it works fine, but I wouldn't consider migration from 2.5 to 3.1 because of compatibility issues. – Rrr Apr 09 '12 at 18:04
  • OK, cool if you solved the issue :) About the different version this might not be an issue in this case, though many tools lib releases components made to work together and then with the same version. Also could you develop the compatibility issues between 2.5 and 3.1, if you don't update now, you might be caught later on, it might be a technical debt. – bric3 Apr 09 '12 at 18:21
  • Yep, I've already faced with compatibility issues, take a look at my comment here http://stackoverflow.com/a/10049643/1063824 – Rrr Apr 10 '12 at 19:06
  • Actually about the classextension, it is available on maven, look for `org.easymock:easymockclassextension:3.1`. Though I strongly advise you to upgrade your code and remove that dependency as EasyMock and EasyMock CE have merged. Note that it's normal for projects to change their API or part of it over time and releases, but making it painless is a real challenge, API design is really difficult. And sometime you hit a snag, that's why major versions can introduce breaking API change. Anyway, good luck for the work ahead. – bric3 Apr 11 '12 at 09:26