'Counting method invocations in Unit tests

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



Solution 1:[1]

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

Solution 2:[2]

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

Solution 3:[3]

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

Solution 4:[4]

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

Solution 5:[5]

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.

Solution 6:[6]

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

Solution 7:[7]

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.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Naman
Solution 2 Jakub Kubrynski
Solution 3 OlivierTerrien
Solution 4 oleh.kovaliuk
Solution 5
Solution 6 vazor
Solution 7 Mark Robinson