gpt4 book ai didi

EasyMock 与 Mockito : design vs maintainability?

转载 作者:行者123 更新时间:2023-12-03 06:08:19 26 4
gpt4 key购买 nike

思考这个问题的一种方法是:如果我们关心代码的设计,那么 EasyMock 是更好的选择,因为它通过其期望概念向您提供反馈。

如果我们关心测试的可维护性(更容易阅读、编写并且测试不那么脆弱,不受变化的影响),那么 Mockito 似乎是更好的选择。

我的问题是:

  • 如果您在大型项目中使用过 EasyMock,您是否发现您的测试更难维护?
  • Mockito(内切测试除外)有哪些限制?

最佳答案

我不会争论这些框架的测试可读性、大小或测试技术,我相信它们是相同的,但通过一个简单的示例,我将向您展示差异。

假设:我们有一个类负责在某处存储某些内容:

public class Service {

public static final String PATH = "path";
public static final String NAME = "name";
public static final String CONTENT = "content";
private FileDao dao;

public void doSomething() {
dao.store(PATH, NAME, IOUtils.toInputStream(CONTENT));
}

public void setDao(FileDao dao) {
this.dao = dao;
}
}

我们想测试它:

莫基托:

public class ServiceMockitoTest {

private Service service;

@Mock
private FileDao dao;

@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
service = new Service();
service.setDao(dao);
}

@Test
public void testDoSomething() throws Exception {
// given
// when
service.doSomething();
// then
ArgumentCaptor<InputStream> captor = ArgumentCaptor.forClass(InputStream.class);
Mockito.verify(dao, times(1)).store(eq(Service.PATH), eq(Service.NAME), captor.capture());
assertThat(Service.CONTENT, is(IOUtils.toString(captor.getValue())));
}
}

EasyMock:

public class ServiceEasyMockTest {
private Service service;
private FileDao dao;

@Before
public void setUp() {
dao = EasyMock.createNiceMock(FileDao.class);
service = new Service();
service.setDao(dao);
}

@Test
public void testDoSomething() throws Exception {
// given
Capture<InputStream> captured = new Capture<InputStream>();
dao.store(eq(Service.PATH), eq(Service.NAME), capture(captured));
replay(dao);
// when
service.doSomething();
// then
assertThat(Service.CONTENT, is(IOUtils.toString(captured.getValue())));
verify(dao);
}
}

正如您所看到的,两个测试都相当相同,并且都通过了。现在,让我们想象一下其他人更改了服务实现并尝试运行测试。

新服务实现:

dao.store(PATH + separator, NAME, IOUtils.toInputStream(CONTENT));

在 PATH 常量末尾添加分隔符

现在测试结果如何?首先,两个测试都会失败,但会出现不同的错误消息:

EasyMock:

java.lang.AssertionError: Nothing captured yet
at org.easymock.Capture.getValue(Capture.java:78)
at ServiceEasyMockTest.testDoSomething(ServiceEasyMockTest.java:36)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

莫基托:

Argument(s) are different! Wanted:
dao.store(
"path",
"name",
<Capturing argument>
);
-> at ServiceMockitoTest.testDoSomething(ServiceMockitoTest.java:34)
Actual invocation has different arguments:
dao.store(
"path\",
"name",
java.io.ByteArrayInputStream@1c99159
);
-> at Service.doSomething(Service.java:13)

EasyMock 测试中发生了什么,为什么没有捕获结果?是不是store方法没有执行,但是等一下,是的,为什么EasyMock要骗我们呢?

这是因为 EasyMock 在一行中混合了两种职责 - stub 和验证。这就是为什么当出现问题时很难理解哪个部分导致了故障。

当然你可以告诉我 - 只需更改测试并在断言之前移动验证即可。哇,你是认真的吗,开发人员应该记住一些由模拟框架强制执行的神奇命令吗?

顺便说一句,这没有帮助:

java.lang.AssertionError: 
Expectation failure on verify:
store("path", "name", capture(Nothing captured yet)): expected: 1, actual: 0
at org.easymock.internal.MocksControl.verify(MocksControl.java:111)
at org.easymock.classextension.EasyMock.verify(EasyMock.java:211)

不过,它告诉我该方法没有执行,但它确实执行了,只是带有另一个参数。

为什么 Mockito 更好?该框架不会在一个地方混合两种职责,当您的测试失败时,您会很容易理解原因。

关于EasyMock 与 Mockito : design vs maintainability?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2864796/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com