fracz
fracz

Reputation: 21278

Check if method was called on EasyMock

Using EasyMock 3.2. In order to unit test an UI, I have to mock some dependencies. One of them is Page. Base class for UI tests looks like this:

abstract class AbstractUiTest {
    @Before
    public function setUpUiDependencies() {
        Page page = createNiceMock(Page.class);
        Ui.setCurrentPage(page);
    }
}

Most of the time I don't use the page explicity, it's just there not to throw NullPointerException when e.g. Ui calls getPage().setTitle("sth") etc.

However, in a few tests I want to explicity check if something has happend with the page, e.g.:

public class SomeTest extends AbstractUiTest {
    @Test
    public void testNotification() {
        // do something with UI that should cause notification
        assertNotificationHasBeenShown();
    }

    private void assertNotificationHasBeenShown() {
        Page page = Ui.getCurrentPage(); // this is my nice mock
        // HERE: verify somehow, that page.showNotification() has been called
    }
}

How to implement the assertion method? I would really want to implement it without recording behavior to the page, replaying and verifying it. My problem is a bit more complicated, but you should get the point.

Upvotes: 3

Views: 13261

Answers (2)

andrea
andrea

Reputation: 521

Use a nice mock in the tests where you don't care what happens to page and a normal mock in those tests where you want to test something explicit - and use expect, verify etc. I.e. have two variables in your setup method: nicePage (acts as a stub) and mockPage (acts as a mock)

Upvotes: 0

David Conrad
David Conrad

Reputation: 16419

EDIT: I think that perhaps this is not really needed, since simply using replay and verify should check that the expected methods were actually called. But you said you want to do this without replaying and verifying. Can you explain why you have that requirement?

I think that you can use andAnswer and an IAnswer. You don't mention what the return value of page.showNotification() is. Assuming it returns a String, you could do this:

import static org.easymock.EasyMock.expect;
import static org.junit.Assert.assertTrue;

import java.util.concurrent.atomic.AtomicBoolean;

import org.easymock.IAnswer;
import org.junit.Ignore;
import org.junit.Test;

public class SomeTest extends AbstractUiTest {
    @Test
    public void shouldCallShowNotification() {
        final AtomicBoolean showNotificationCalled = new AtomicBoolean();
        expect(page.showNotification()).andAnswer(new IAnswer<String>() {
            @Override
            public String answer() {
                showNotificationCalled.set(true);
                return "";
            }
        });

        replay(page);
        Ui.getCurrentPage();
        verify(page);

        assertTrue("showNotification not called", showNotificationCalled.get());
    }
}

If showNotification returns void, I believe you would need to do this:

import static org.easymock.EasyMock.expectLastCall;
import static org.junit.Assert.assertTrue;

import java.util.concurrent.atomic.AtomicBoolean;

import org.easymock.IAnswer;
import org.junit.Ignore;
import org.junit.Test;

public class SomeTest extends AbstractUiTest {
    @Test
    public void shouldCallShowNotification() {
        final AtomicBoolean showNotificationCalled = new AtomicBoolean();
        page.showNotification();
        expectLastCall().andAnswer(new IAnswer<Void>() {
            @Override
            public Void answer() {
                showNotificationCalled.set(true);
                return null;
            }
        });

        replay(page);
        Ui.getCurrentPage();
        verify(page);

        assertTrue("showNotification not called", showNotificationCalled.get());
    }
}

Note: I've used an AtomicBoolean to record whether the method was called. You could also use a boolean array of a single element, or your own mutable object. I used AtomicBoolean not for its concurrency properties, but simply because it is a handy mutable boolean object that is already present in the Java standard libraries.

The other thing that I have done to verify that a method was being called is to not use a mock at all, but to create an instance of Page as an anonymous inner class and override the showNotification method, and record somewhere that the call occurred.

Upvotes: 2

Related Questions