Search code examples
javaspringunit-testingjunitjunit5

doNothing when on abstract class method but should work when called from concreate class instance


I have following structure:

class Sample {
 private Map<String A> serviceMap;

 @Autowired
 private List<A> services;

 @PostConstruct
 public void init() {
  this.serviceMap = this.services.stream().collect(Collectors.toMap(A::getName, s -> s)); 
 }

 public void doSomething() {
   // Some logic, and gets the serviceName
   this.serviceMap.get(serviceName).process(...);
 }
}

Now how to test this doSomething method of Sample class. I don't want to call the process method of Abstract class A.

I tried to MockBean the services but the problem is how to use doNothing when for this line this.serviceMap.get(serviceName).process(...);.


Solution

  • You can add a getter function for serviceMap. The getter will be package-private for testing purposes.

    class Sample {
     private Map<String A> serviceMap;
    
     @Autowired
     private List<A> services;
    
     @PostConstruct
     public void init {
      this.serviceMap = this.services.stream().collect(Collectors.toMap(A::getName, s -> s)); 
     }
    
     public void doSomething {
       // Some logic, and gets the serviceName
       getServiceMap().get(serviceName).process(...);
     }
    
     Map<String A> getServiceMap(){
       return this.serviceMap;
     }
    }
    

    Then in your test -

    //Given
    var sampleSpy = spy(Sample.class);
    var serviceMapMock = mock(Map.class);
    var serviceAMock = mock(A.class);
    when(sampleSpy.getServiceMap()).thenReturn(serviceMapMock);
    when(serviceMapMock.get(any())).thenReturn(serviceAMock);
    doNothing().when(serviceAMock).process();
    
    //When
    sample.doSomething();
    
    //Then
    //assertions