【问题标题】:Mock Beans from Spring Context来自 Spring 上下文的模拟 Bean
【发布时间】:2016-01-27 09:26:45
【问题描述】:

我想使用模拟的存储库 bean 创建使用 Spring 上下文的测试。我正在使用 Spring Boot 1.3.2.BUILD-SNAPSHOT + JUnit + Mockito。

这是我的测试配置类:

@ComponentScan(basePackages = "myapp", excludeFilters =
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,
        value = {
                OfferRepository.class
        }
)
)
@Configuration
public class TestEdge2EdgeConfiguration {

    @Bean
    public OfferRepository offerRepository() {
       return mock(OfferRepository.class);
    }

}

此配置的目的是从 Spring Context 中排除 OfferRepository 并对其进行模拟,多亏了这一点,我将能够编写使用 Spring Context 和模拟数据库 Repository 的测试。

这是我的测试类:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {TestEdge2EdgeConfiguration.class})
@WebAppConfiguration
public class OfferActionsControllerTest {

    @Autowired
    private OfferRepository offerRepository;

    @Autowired
    private OfferActionsController offerActionsController;

    @Before
    public void setUp(){
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void saveOffer() {
        //given
        BDDMockito.given(offerRepository.save(any(Offer.class))).willReturn(new Offer());
        //when
        ResponseEntity<Offer> save = offerActionsController.save(new Offer());

        //then
        org.springframework.util.Assert.notNull(save);
    }
}

测试和测试配置目录是:

src/test/java/myapp 

我的应用程序配置和包含 OfferRepository 目录的包是:

src/main/java/myapp/

问题是 Spring Boot 没有从 TestEdge2EdgeConfiguration.class 加载我的配置,并且永远不会创建 OfferRepository 的模拟。

有没有人可以帮我解决这个问题?

【问题讨论】:

  • 你试过@ContextConfiguration(TestEdge2EdgeConfiguration.class) 吗?
  • SpringApplicationConfiguration 与标准的@ContextConfiguration 类似,但使用了 Spring Boot 的 SpringApplicationContextLoader
  • 我不知道 ComponentScan$Filter 注释,但是在阅读了文档之后,如果我理解正确,为什么在这种情况下需要它?没有过滤器是否可以工作?
  • 我想从上下文中排除 Bean OfferRepository,并将其替换为我的模拟 OfferRepository
  • 只是猜测,但您不是排除了所有类型为 OfferRepository 的 bean,即真实的和模拟的?

标签: spring unit-testing junit spring-boot


【解决方案1】:

这就是你应该做的事情(假设你正在为 offerActionsController 编写一个测试并注入 offerRepository):

@Mock
private OfferRepository offerRepository;

@InjectMocks
private OfferActionsController offerActionsController;

@Before
public void setUp(){
    MockitoAnnotations.initMocks(this);
}

你可以这样写你的测试方法:

@Test
public void saveOffer() {
    /* Given */
    Mockito.when(offerRepository.save(Mockito.any(Offer.class))).thenReturn(new Offer());

    //when
    ResponseEntity<Offer> save = offerActionsController.save(new Offer());

    //then
    org.springframework.util.Assert.notNull(save);
}

【讨论】:

  • 如果我想编写单元测试,这没关系,你是对的,但我想用模拟数据库编写集成测试,所以我需要为我的 puprouse 和模拟存储库 bean 设置 spring 上下文。跨度>
  • 在你的类中为offerRepository 创建一个setter,然后将你的模拟对象从你的测试类传递给setter。
  • 我在引擎盖下有更深的结构。控制器 -> 服务 -> 存储库。所以我需要 Spring Context 和 mock Repository
【解决方案2】:

使用Spingockito 将bean 替换为使用@ReplaceWithMock 的模拟。如果您需要在测试中访问模拟 bean,请不要忘记使用 @Autowired@ReplaceWithMock

【讨论】:

  • 感谢您的建议,我试图这样做,但 Spingockito 接缝不适用于 SpringBoot。嗯,我希望我能找到解决方案,但我认为 @SpringBootApplication 无法在 Spring Context 中模拟 bean。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-15
  • 1970-01-01
  • 2013-03-12
  • 1970-01-01
  • 2021-12-16
  • 2014-09-12
  • 1970-01-01
相关资源
最近更新 更多