如何在 Spring Boot 中创建一个调用包含构造函数注入的服务的测试?

Posted

技术标签:

【中文标题】如何在 Spring Boot 中创建一个调用包含构造函数注入的服务的测试?【英文标题】:How to create a test in Springt Boot that calls a service which includes constructor injection? 【发布时间】:2019-12-27 12:37:50 【问题描述】:

我正在尝试在 Spring-Boot 项目中编写测试。我的问题是我不能使用包含构造函数注入的服务。

根据我的尝试,我会收到 java.lang.IllegalStateException: Failed to load ApplicationContexts 或 NullPointerExceptions 之类的错误。

我的第一次尝试是将服务中的构造函数注入更改为字段注入。但是在阅读了post之后,我决定将其改回以前的方式。 然后我搜索了示例,但找不到有用的东西。

以下是相关代码sn-ps。如果需要更多代码,我会提供。

带有构造函数注入的服务类:

PlayerServiceImpl.java

@Service
public class PlayerServiceImpl implements PlayerService 

    private PlayerRepository playerRepository;
    private CompanyService companyService;
    private CompanyResourceService companyResourceService;

    @Autowired
    public PlayerServiceImpl(PlayerRepository thePlayerRepository, CompanyService theCompanyService,
                             CompanyResourceService theCompanyResourceService) 
        this.playerRepository = thePlayerRepository;
        this.companyService = theCompanyService;
        this.companyResourceService = theCompanyResourceService;
    

...


我正在尝试创建的测试类:

PlayerServiceImplIntegrationTest.java

@RunWith(SpringRunner.class)
@SpringBootTest
public class PlayerServiceImplIntegrationTest 

    @TestConfiguration
    static class PlayerServiceImplTestContextConfiguration 

        private PlayerRepository playerRepository;
        private CompanyService companyService;
        private CompanyResourceService companyResourceService;

        @Bean
        public PlayerService playerService() 
            return new PlayerServiceImpl(playerRepository, companyService, companyResourceService);
        
    

    @Autowired
    private PlayerService playerService;

    @MockBean
    private PlayerRepository playerRepository;

    @Before
    public void setUp() 
        Player max = new Player("MaxMustang", "test123", "MaxMustang",
                "max.mustang@test.com", new Date(System.currentTimeMillis()), 1, 0,
                new BigDecimal("0.00"), new BigDecimal("0.00"), 0, 0);

        Mockito.when(playerRepository.findByUserName(max.getUserName()))
                .thenReturn(max);
    

    @Test
    public void whenFindById_thenReturnPlayer() 
        String userName = "MaxMustang";

        Player found = playerService.findByUserName(userName);

        assertThat(found.getUserName()).isEqualTo(userName);
    

在我的测试中,我试图创建一个播放器对象并接收它。这只是我在 Spring Boot 中的第一次测试。我的主要目标是让测试运行起来。 原始测试来自“5. Mocking with @MockBean”中的Baeldung。但是在进行试验时,我添加或更改了一些东西。

如果我错过了指向同一问题的帖子,我会很高兴得知这一点。

另外,如果有人能告诉我我的服务的构造函数中的参数是否过多或仍在“ok”范围内,我将不胜感激。

【问题讨论】:

您有两个类创建 PlayerService 类型的 bean,并且在一个类中传递空对象?忽略 TestConfiguration 类并尝试它 好的,知道它有效。我想,我必须实现一个@TestConfiguration 类。非常感谢! 【参考方案1】:

您必须将配置 bean 设为主要,并在该方法上使用构造函数注入:

    @TestConfiguration
    static class PlayerServiceImplTestContextConfiguration 

      @Bean
      @Primary
      public PlayerService playerService(PlayerRepository playerRepository,
            CompanyService companyService, CompanyResourceService companyResourceService) 
        return new PlayerServiceImpl(playerRepository, companyService, companyResourceService);
      
    

如果没有primary,您将有两个相同类型的bean 浮动,并且您不要在这里使用@Qualifier。此外,您不能在配置类中使用 @Autowire bean,这就是您需要使用构造函数注入的原因。

【讨论】:

这也行得通!谢谢,但你能告诉我哪种方法更好吗?有或没有@TestConfiguration@Primary 和我的 @TestConfiguration 类是静态的这一事实是否会影响我的服务或控制器类? 如果在这种情况下不能使用 MockBean,@TestConfiguration 很好

以上是关于如何在 Spring Boot 中创建一个调用包含构造函数注入的服务的测试?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Spring Boot 中创建不同的 ThreadPoolTask​​Executor? [复制]

我如何在 Spring Boot/MVC 中创建错误处理程序(404、500...)

如何在spring boot webflux中创建动态过滤器?

如何在 Spring Boot 应用程序中创建第二个 RedisTemplate 实例

Spring Boot:如果不存在,则在启动时在 mongodb 中创建文档

如何在 Spring Boot 中创建自定义错误页面