【问题标题】:mock beans inside a method and those beans are also autowired in the same class or super class在方法中模拟 bean,并且这些 bean 也自动装配在同一个类或超类中
【发布时间】:2018-07-29 16:29:58
【问题描述】:
@RunWith(SpringRunner.class)
@WebAppConfiguration
Class Test{

@Autowired
public SomeBean someBean;

@Test
public void testAccountPage2() throws Exception {
 SomeBean someBean = mock(SomeBean.class);  
 given(someBean.getAccount(anyString())).willReturn(getCustomer());
}

这里someBean.getAccount(anyString()) 不是在模拟,而是在调用该bean impl 的实际方法。似乎它正在使用 Autowired 对象而不是模拟对象。

谁能帮我在方法级别模拟 bean?这些 bean 也自动装配在同一个类或超类中。

谢谢

【问题讨论】:

  • 那根本行不通。您只能在类级别模拟它们,以便 Spring Boot 将它们考虑在内。
  • 如果我们尝试像这样模拟,那么在方法内部呢? SomeBean someBean = mock(SomeBean.class);行不行?
  • 有什么不清楚的根本行不通。是的,您得到了一个模拟,没有 Spring Boot 对此一无所知,并且在内部它仍将使用正常的依赖项。这只适用于@MockBean

标签: spring-boot junit


【解决方案1】:

要用 Mockito 模拟替换 Spring 容器中的 bean,请使用 @MockBean

import org.springframework.boot.test.mock.mockito.MockBean; // import to add

@RunWith(SpringRunner.class)
@WebAppConfiguration
Class Test{

  @MockBean
  public SomeBean someBean;

  @Test
  public void testAccountPage2() throws Exception {      
    given(someBean.getAccount(anyString())).willReturn(getCustomer());
  }
}

要了解Spring Boot中MockitoMockBean的区别,可以参考this question

【讨论】:

  • 实际上我可以使用 mockbean 注释来模拟 bean,但我想在同一个类中同时使用 autowired 和 mockbean。例如,autowired 可用于类级别,mock 对象可用于方法级别。春季junit测试有可能吗?
  • 不,不可能开箱即用。要实现这样的事情,您应该检索要注入模拟的依赖项并手动设置模拟。它制作了很多样板代码,并且不一致,因为所有其他依赖项都不会更新。也许您应该通过解释您的要求而不是解决方案来完善您的问题。
  • 谢谢 davidxxx,我想测试我的控制器,我想在其中为部分测试用例调用真实的服务方法,为剩余的测试用例调用模拟方法方法。请建议我如何实现这一目标?
  • 不客气 :) 我认为更简洁的方法是定义两个测试类:一个模拟一些依赖项的单元测试类和一个不模拟的集成测试类。
【解决方案2】:

您需要注入模拟以使其工作而不是自动装配

//if you are just testing bean/services normally you do not need the whole application context
@RunWith(MockitoJUnitRunner.class)
public class UnitTestExample {

    @InjectMocks
    private SomeBean someBean = new SomeBean();

    @Test
    public void sampleTest() throws Exception {
        //GIVEN

        given(
            someBean.getAccount(
            //you should add the proper expected parameter
                any()
            )).willReturn(
            //you should add the proper answer, let's assume it is an Account class
            new Customer()
        );

        //DO
        //TODO invoke the service/method that use the getAccount of SomeBean
        Account result = someBean.getAccount("");

        //VERIFY
        assertThat(result).isNotNull();
        //...add your meaningful checks
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-14
    • 1970-01-01
    • 2011-05-26
    • 2012-12-30
    相关资源
    最近更新 更多