计算单元测试中的方法调用次数

发布于 2024-12-08 18:54:58 字数 42 浏览 0 评论 0原文

在单元测试中计算方法调用的最佳方法是什么?有任何测试框架允许这样做吗?

What is the best way to count method invocations in a Unit Test. Do any of the testing frameworks allow that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

浅笑依然 2024-12-15 18:54:58

听起来您可能想要使用模拟框架通常提供的 .expects(1) 类型方法。

使用mockito,如果您正在测试一个列表并想要验证clear被调用了3次并且add被使用这些参数至少调用了一次,您可以执行以下操作:

List mock = mock(List.class);        
someCodeThatInteractsWithMock();                 

verify(mock, times(3)).clear();
verify(mock, atLeastOnce()).add(anyObject());      

Source - MockitoVsEasyMock

It sounds like you may want to be using the .expects(1) type methods that mock frameworks usually provide.

Using mockito, if you were testing a List and wanted to verify that clear was called 3 times and add was called at least once with these parameters you do the following:

List mock = mock(List.class);        
someCodeThatInteractsWithMock();                 

verify(mock, times(3)).clear();
verify(mock, atLeastOnce()).add(anyObject());      

Source - MockitoVsEasyMock

债姬 2024-12-15 18:54:58

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

In Mockito you can do something like this:

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();
你爱我像她 2024-12-15 18:54:58

给定一个示例类“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";
        }
    }
}

Given an example class "RoleRepository" with a single method "getRole(String user)" which would return a role.

Assuming you have declared this object as Mock or Spy and you want to check whether the method getRole(String) is called for once a time.

You would do something like: 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";
        }
    }
}
仄言 2024-12-15 18:54:58

您可以使用 Mockito 中的 Answer 接口来统计方法调用的次数。

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

You can count number of method invocation by using interface Answer in Mockito.

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);
猥︴琐丶欲为 2024-12-15 18:54:58

根据您想要计数的方法,您可以创建一个测试配置,并使用与您的类/包/方法匹配的 @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
}

您可以通过上述或 XML 配置使用 vanilla AspectJ 或 Spring AOP,如果你会发现这更容易。

如果需要,您可以创建不同的切入点/方面。

Depending on what methods you want to count, you can create a test config, with a @Before advice matching your class / package / method:

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
}

You can use vanilla AspectJ or Spring AOP via above or XML configs if you find it easier.

You can create different pointcuts / aspect if you need to.

千寻… 2024-12-15 18:54:58

听起来您可能需要一个测试间谍。例如,请参见 Mockito.spy()

It sounds like you may want a test spy. See, for example, Mockito.spy().

娇柔作态 2024-12-15 18:54:58

您有几个选项

1)添加一些特殊代码来计算函数中的调用次数。它会起作用,但这不是一个很好的解决方案。

2) 运行单元测试后,检查代码覆盖率。大多数覆盖率工具都会计算调用次数,但它们实际上是为后处理而设计的。

3)使用分析器。探查器可以让您计算函数被调用的次数。这是一个非常手动的过程,因此它并不是真正为单元测试而设计的。

更好的解决方案是检查输出是否符合您的预期,而不是检查其内部工作原理。

You've got a few options

1) Add some special code which counts invocations in the function. It will work, but it's not a great solution.

2) After you run your unit tests, check the code coverage. Most coverage tools will count invocations but they are really designed for post-processing.

3) Use a profiler. A profiler will let you count how many times a function is invoked. This is a very manual process so it's not really designed for unit testing.

A better solution would be to check that output is what you expect rather than checking how it works internally.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文