检查方法是否在EasyMock上调用

时间:2014-05-21 21:03:28

标签: java unit-testing mocking easymock

使用EasyMock 3.2。为了对UI进行单元测试,我必须模拟一些依赖项。其中一个是Page。 UI测试的基类如下所示:

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

大部分时间我都没有使用页面显式,只是在那里不会抛出NullPointerException,例如Ui打电话给getPage().setTitle("sth")等。

然而,在一些测试中,我想明确检查页面是否发生了某些事情,例如:

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
    }
}

如何实现断言方法?我真的想要实现它而不记录页面的行为,重放和验证它。我的问题有点复杂,但你应该明白这一点。

2 个答案:

答案 0 :(得分:2)

编辑:我认为这可能并不是真的需要,因为只需使用重播验证就应该检查实际调用了预期的方法。但是你说你想在不重播和验证的情况下这样做。你能解释一下为什么你有这个要求吗?

我认为您可以使用andAnswerIAnswer。你没有提到page.showNotification()的返回值是什么。假设它返回一个String,你可以这样做:

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());
    }
}

如果showNotification返回void,我相信你需要这样做:

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());
    }
}

注意:我已使用AtomicBoolean来记录方法是否被调用。您还可以使用单个元素的布尔数组或您自己的可变对象。我使用AtomicBoolean不是因为它的并发属性,而只是因为它是一个方便的可变布尔对象,已经存在于Java标准库中。

我验证调用方法的另一件事是根本不使用mock,而是创建Page的实例作为匿名内部类并覆盖showNotification方法,并记录某个地方打电话。

答案 1 :(得分:0)

在测试中使用一个漂亮的模拟,你不关心页面发生了什么,在那些你想要测试一些东西的测试中使用普通的模拟 - 并使用expect,验证等等。在你的setup方法中有两个变量:nicePage(充当存根)和mockPage(充当模拟)