Spring boot 如何使用Mockito模拟context.getBeansWithAnnotations

Spring boot 如何使用Mockito模拟context.getBeansWithAnnotations,spring-boot,mockito,junit4,Spring Boot,Mockito,Junit4,我创建了一个带有两个具体实现的接口客户端 clientA和clientB,并用我的自定义注释对它们进行注释 public interface Client{ public void dosomething(); } @Component @Myannotation public class clientA implements Client { public void doSomething(){ sysout("Client A do so

我创建了一个带有两个具体实现的接口客户端 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类调用clientA和clientB的重写方法

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

   }
}
1) 如何编写testperformOperation方法(允许将performOperation方法的返回类型从void更改为任何其他类型)


2) 有没有更好的方法可以在不创建自定义注释的情况下获取客户端接口的所有实现的列表。

我将回答您问题的两个部分,但我认为第一种方法较差,第二种方法是go-to方法

  • 如果你想坚持你的自定义注释方法,你需要在你的测试类中有一个
    @Mock-ApplicationContext-ApplicationContext
    。在测试方法(或设置方法)中,您需要模拟对
    applicationContext.getBeansWithAnnotation的调用,并返回包含bean的适当映射(可能也是模拟)

  • 通过注入适当类型的列表,可以轻松地将所有bean注入到类中。就你而言

    • 摆脱@Autowired ApplicationContext
    • 添加@Autowired列表(或者最好使用构造函数注入)
  • 这也将使测试更简单,无需模拟ApplicationContext。
    例如,请参见

    我建议您首先重构Alien,使用依赖项注入的思想使其更易于测试,其依赖项(即客户端)可以从外部注入,而不是在始终从spring上下文获取的方法中硬编码:

    @组件
    公共类外国人{
    private List clients=new ArrayList();
    @自动连线
    公共外侨(名单客户){
    这个。客户=客户;
    }
    公共行政运作{
    用于(客户c:客户){
    c、 doSomething();
    }
    }
    }
    
    如果您只是想将所有客户端实现注入到Alien中,那么只需将
    @Autowired List
    注入Alien中,Spring将帮助您将所有客户端实现注入到Alien中。无需创建
    @Myannotation

    一旦您使外星人的依赖项可注入(即客户端列表),您只需向其注入一个模拟,并验证
    performOperation()
    是否真正调用了
    客户端的所有
    doSomething()

    @RunWith(MockitoJUnitRunner.class)
    等级分配表{
    @嘲弄
    私人客户mockClientA;
    @嘲弄
    私人客户mockClientB;
    @试验
    公共无效测试性能操作(){
    List clients=new ArrayList();
    添加(mockClientA);
    clients.add(mockClientB);
    外国人=新外国人(客户);
    执行操作();
    验证(mockClientA).doSomething();
    验证(mockClientB).doSomething();
    }
    }
    
    是。我打字的错误太多了。刚刚修改。谢谢如果我想使用
    @InjectMocks Alien
    ,而不是
    Alien Alien=new Alien(clients)
    ,需要做哪些更改?
    @RunWith(MockitoJUnitRunner.class)
    class AlienTest
    {
       @InjectMocks
       Alien a;
    
       @Test
       public void testperformOperation(){
           //how to Mock for beans
           assertEquals(expected, a.performOperation());
       }
    }