如何在 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 ApplicationContext
s 或 NullPointerException
s 之类的错误。
我的第一次尝试是将服务中的构造函数注入更改为字段注入。但是在阅读了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 中创建不同的 ThreadPoolTaskExecutor? [复制]
我如何在 Spring Boot/MVC 中创建错误处理程序(404、500...)
如何在spring boot webflux中创建动态过滤器?
如何在 Spring Boot 应用程序中创建第二个 RedisTemplate 实例