I have created an interface Client with its two concrete implementations clientA and clientB and annotated them with my custom annotation.
public interface Client{
public void dosomething();
}
@Component
@Myannotation
public class clientA implements Client {
public void doSomething(){
sysout("Client A do something");
}
}
@Component
@Myannotation
public class clientB implements Client {
public void doSomething(){
sysout("Client B do something");
}
}
Now I am calling the overriden methods of both clientA and clientB from Alien class.
@Component
class Alien{
@Autowired
private ApplicationContext context;
public void performOperation(){
Map<String, Object> beans =
context.getBeansWithAnnotation(MyAnnotation.class);
for(Map.Entry<String, Object> entry: beans.entrySet()) {
Client c = (Client)entry.getValue();
c.doSomething();
}
}
}
I am facing problem with writing test method for performOperation.
@RunWith(MockitoJUnitRunner.class)
class AlienTest
{
@InjectMocks
Alien a;
@Test
public void testperformOperation(){
//how to Mock for beans
assertEquals(expected, a.performOperation());
}
}
1) How should I write testperformOperation method(allowed to change the return type of performOperation method from void to any other type)
2) Is there any better way to get list of all implementations for Client interface without creating custom annotations.
I would suggest you first refactoring Alien to make it more testable using Dependency Injection idea which its dependencies (i.e Client) can be injected from outside rather than hard coded inside a method which always get from the spring context:
@Component
public class Alien{
private List<Client> clients = new ArrayList<>();
@Autowired
public Alien(List<Client> clients) {
this.clients = clients;
}
public void performOperation(){
for(Client c: clients) {
c.doSomething();
}
}
}
If you simply want to inject all Client implementation to the Alien , you just need to @Autowired List<Client>
into Alien which Spring will already help you to inject all the Client implementation to it out of the box. No need to create @Myannotation
Once you make the Alien 's dependencies injectable (i.e a list of client) , you can simply inject a mock to it and verify performOperation()
really invoke all of Client
's doSomething()
:
@RunWith(MockitoJUnitRunner.class)
class AlienTest{
@Mock
private Client mockClientA;
@Mock
private Client mockClientB;
@Test
public void testperformOperation(){
List<Client> clients = new ArrayList<>();
clients.add(mockClientA);
clients.add(mockClientB);
Alien alien = new Alien(clients);
alien.performOperation();
verify(mockClientA).doSomething();
verify(mockClientB).doSomething();
}
}