>我创建了一个接口客户端及其两个具体实现 clientA 和 clientB 并用我的自定义注释对它们进行了注释。
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");
}
}
现在我从 Alien 类调用客户端 A 和客户端 B 的覆盖方法。
@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();
}
}
}
我在编写执行操作的测试方法时遇到问题。
@RunWith(MockitoJUnitRunner.class)
class AlienTest
{
@InjectMocks
Alien a;
@Test
public void testperformOperation(){
//how to Mock for beans
assertEquals(expected, a.performOperation());
}
}
1) 我应该如何编写testperform操作方法(允许将 performOperation 方法的返回类型从 void 更改为任何其他类型)
2)有没有更好的方法来获取客户端接口的所有实现列表,而无需创建自定义注释。
我建议您首先重构 Alien,以使用依赖注入的想法使其更易于测试,它的依赖项(即客户端)可以从外部注入,而不是在始终从 spring 上下文获取的方法中硬编码:
@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();
}
}
}
如果你只是想将所有客户端实现注入到Alien,你只需要@Autowired List<Client>
到Alien中,Spring 已经帮助你开箱即用地将所有客户端实现注入到它。无需创建@Myannotation
一旦你使Alien的依赖可注入(即客户端列表),你可以简单地向它注入一个模拟并验证performOperation()
真的调用Client
的所有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();
}
}
我会回答你问题的两部分,但我相信第一种方法较差,第二种方法是首选方法。
-
如果要坚持使用自定义注释方法,则需要在测试类中有一个
@Mock ApplicationContext applicationContext
。在测试方法(或设置方法)中,您需要模拟对applicationContext.getBeansWithAnnotation
的调用并返回包含您的 bean 的适当映射(也可能是一个模拟) -
您可以通过注入适当类型的 List 轻松地将所有 bean 注入到类中。在您的情况下
- 摆脱@Autowired应用程序上下文
- 添加@Autowired列表(或者最好使用构造函数注入)
这也将使测试更简单,无需模拟 ApplicationContext。 例如,请参阅 https://dzone.com/articles/load-all-implementors