Skip to content

How to create an argument captor for a Map object in mockito in java?

How to create an argument captor for Map<String, SomeCustomClass>?

I have the code that follows the following pattern:

import java.util.HashMap;
import java.util.Map;

public class CompoundClass {

   public CompoundClass (String a, String b){
       this.a = a;
       this.b = b;
   }

   public String a;
   public String b;
}

public class SubClass {
    public void doSomeThingSubClass(Map<String, CompoundClass> mapSb) {
        ...
    }
}

public class Example {

    public SubClass sb;

    public Example(SubClass sb) {
        this.sb = sb;
    }

    public void doSomeThing () {
        Map<String, CompoundClass> mapSb = new HashMap<>();
        mapSb.put("x", new CompoundClass("aa","bb"));
        sb.doSomeThingSubClass(mapSb);
    }
}

And I want to test if the method doSomethingSubClass(mapSb) was called, whereby I need to be able to check with what argument it was called. For this purpose I have the following unit test:

@Test
void TestDoSomehing(){
    SubClass sb = mock(SubClass.class);
    
    Example ex = new Example(sb);
    
    ArgumentCaptor<Map<String, CompoundClass>> argCaptor = ArgumentCaptor.forClass(Map<String, CompoundClass>.class);

    ex.doSomeThing();

    verify(sb).doSomeThingSubClass(argCaptor.capture());
    
    System.out(argCaptor.getValue().get('x').a);
}

The problem is that the above initialization of the argCaptor produces the following error message: “Cannot select from parametrized type”. Therefore, the question is how to declare an initialize in a correct way the argument captor for a map object like Map<String, SomeCustomeClass>? Thanks in advance!

Answer

You can do it either:

with @SuppressWarnings(“unchecked”)

  @Test
  @SuppressWarnings("unchecked")
  void TestDoSomething(){
    SubClass sb = mock(SubClass.class);

    Example ex = new Example(sb);

    ArgumentCaptor<Map<String, CompoundClass>> argCaptor = ArgumentCaptor.forClass(Map.class);

    ex.doSomeThing();

    verify(sb).doSomeThingSubClass(argCaptor.capture());

    System.out.println(argCaptor.getValue().get("x").a);
  }

or with junit5 and @Captor annotation:

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
@TestInstance(Lifecycle.PER_METHOD)
public class TestDoSomething {

  @Captor
  private ArgumentCaptor<Map<String, CompoundClass>> argCaptor;

  @Test
  void TestDoSomething2(){
    SubClass sb = mock(SubClass.class);

    Example ex = new Example(sb);

    ex.doSomeThing();

    verify(sb).doSomeThingSubClass(argCaptor.capture());

    System.out.println(argCaptor.getValue().get("x").a);
  }
}