什么是在单元测试中计算方法调用次数的最佳方法?是否有任何测试框架可以实现这一点?
什么是在单元测试中计算方法调用次数的最佳方法?是否有任何测试框架可以实现这一点?
听起来你可能想使用模拟框架通常提供的.expects(1)
类型方法。
使用Mockito,如果你正在测试一个List并且想要验证clear被调用了3次,add至少被调用了一次且具有这些参数,则可以按照以下方式进行:
List mock = mock(List.class);
someCodeThatInteractsWithMock();
verify(mock, times(3)).clear();
verify(mock, atLeastOnce()).add(anyObject());
来源 - Mockito vs EasyMock
在 Mockito 中,您可以像这样实现:
YourService serviceMock = Mockito.mock(YourService.class);
// code using YourService
// details of all invocations including methods and arguments
Collection<Invocation> invocations = Mockito.mockingDetails(serviceMock).getInvocations();
// just a number of calls of any mock's methods
int numberOfCalls = invocations.size();
Method
对象。参考 Sinon 的 JS API:stub.callCount
。 - oligofren假设有一个名为“RoleRepository”的类,其拥有一个单独的方法“getRole(String user)”,该方法将返回一个角色。
假设您已经将此对象声明为Mock或Spy,并且想要检查方法getRole(String)是否被调用了一次。
您可以这样做:Mockito.verify(roleRepository, Mockito.times(1)).getRole(Mockito.anyString());
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.Spy;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class RoleRepositoryTest {
@Spy
private RoleRepository roleRepository = new RoleRepository();
@Test
public void test() {
roleRepository.getRole("toto");
Mockito.verify(roleRepository, Mockito.times(1)).getRole(Mockito.anyString());
}
public static class RoleRepository {
public String getRole(String user) {
return "MyRole";
}
}
}
ConnectionPool mockedConnectionPool = mock(ConnectionPool.class);
final int[] counter = new int[1];
when(mockedConnectionPool.getConnection()).then(new Answer<Connection>() {
@Override
public Connection answer(InvocationOnMock invocation) throws Throwable {
counter[0]++;
return conn;
}
});
// some your code
assertTrue(counter[0] == 1);
根据您想要计数的方法,您可以创建一个测试配置,其中包含与您的类/包/方法匹配的@Before
建议:
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class MethodCounterAspect {
private int counter = 0 // or inject the Counter object into this aspect
@Pointcut( "execution( * com.sample.your.package.*.*(..) )" )
public void methodsToCount() {}
@Before("methodsToCount()")
public void execute() throws Throwable {
counter++; // or update the counter injected into this aspect..
}
// get the counter
}
如果您觉得更容易使用,可以使用原始的AspectJ或通过以上XML配置使用Spring AOP。
如果需要,您可以创建不同的切入点/方面。
看起来你可能需要一个测试间谍。例如,可以查看Test Spy 和Mockito.spy().
你有几个选项:
1)添加一些特殊代码来计算函数中的调用次数。这样做可以实现,但并不是一个好的解决方案。
2)在运行单元测试后,检查代码覆盖率。大多数覆盖工具会计算调用次数,但它们真正设计的是后处理。
3)使用分析器。分析器将让您计算函数被调用的次数。这是一个非常手动的过程,因此并不是为单元测试而设计的。
更好的解决方案是检查输出是否符合预期,而不是检查其内部工作方式。