【问题标题】:How to mock a dependency for an @Autowire object?如何模拟 @Autowire 对象的依赖项?
【发布时间】:2020-09-08 00:11:36
【问题描述】:

我有一个 @Autowire 对象,其中包含需要模拟其方法调用的字段。

在主类中:

@Component
public class Pizza {
     private Tomato tomato;
     private Cheese cheese;

     @Autowired
     private Pizza(Tomato tomato, Cheese cheese) {
        this.tomato = tomato;
        this.cheese = cheese;
     }
     
     public String arrangePizza(tomato, cheese) {
        Sauce sauce = tomato.createSauce();
        combine(sauce, cheese);
        return "Pizza created!"
     }
}

在测试类中:

@RunWith(SpringRunner.class)
public class TestPizza {
     @Autowire
     private Pizza pizza;

     //probably create instances of cheese and tomato here?


     private void testCreatePizza {
        //here I want to mock tomato.createSauce()
        pizza.arrangePizza(tomato, cheese);
     }
}

我正在尝试使用 Mockito 或 EasyMock 在 testCreatePizza 中模拟方法tomato.createSauce(),但鉴于 Pizza 是自动装配的,我不确定如何执行此操作。我是否必须在测试类中创建 tomatocheese 的 Autowire 实例? spring 会自动知道将构造函数设置为那些实例吗?

【问题讨论】:

    标签: java spring spring-boot unit-testing autowired


    【解决方案1】:

    Mockito 提供 @Mock 注释来模拟对象,并提供 @InjectMocks 注释来将这些模拟注入到自动装配的字段中。

    @RunWith(SpringRunner.class)
    @ExtendWith(MockitoExtension.class)
    public class TestPizza {
    
         @Mock
         private Tomato tomato;
    
         @Mock
         private Cheese cheese;        
    
         @InjectMocks
         private Pizza pizza;
    
         @BeforeEach
         void init() {
             MockitoAnnotations.initMocks(this);
             when(tomato.createSauce()).thenReturn("Spicy Sauce");
         }
    
         @Test
         private void testCreatePizza {
            pizza.createPizza(tomato, cheese);
         }
    }
    

    【讨论】:

      【解决方案2】:

      由于这是标记为 spring-boot,因此还值得指出 @MockBean annotation。 (相关引用:“在上下文中定义的任何现有的相同类型的单个 bean 都将被模拟替换。如果没有定义现有的 bean,将添加一个新的。”)

      这意味着,在你的测试课中,你可以这样做

      @Autowired
      private Pizza pizza;
      
      @MockBean
      private Tomato tomato;
      

      然后像平常一样使用 Mockito 的 when 等等。与其他答案相比,这种方式可以为您节省一两个注释(如果您正在模拟多个事物),以及对 initMocks() 的调用。

      【讨论】:

      • @MockBean 注解是 Spring 的首选解决方案:它将通过 Spring CDI 注册和注入 Mockito 模拟实例。使用 @InjectMocks 注释,依赖注入由 Mockito 完成,它可以在没有 Spring 的情况下工作,但再次需要更多样板代码来进行测试设置。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-13
      • 1970-01-01
      • 1970-01-01
      • 2020-12-09
      相关资源
      最近更新 更多