为了测试端点,我将 JUnit 与 SpringRunner
和 @WebMvcTest
结合使用
@RunWith(SpringRunner::class)
@WebMvcTest(UserEndpoints::class)
class UserEndpointsTest {
}
UserEndpoints
取决于 UserSevice
UserService
依赖于 UserRepository
我会模拟UserRepository
以测试UserEndpoints
@RunWith(SpringRunner::class)
@WebMvcTest(UserEndpoints::class)
class UserEndpointsTest2 {
@Autowired
private val mockMvc:MockMvc?=null
@MockBean
private val userRepository:UserRepository?=null
@InjectMocks
private var userService:UserService?=null
@Before
fun setup() {
initMocks(this)
Mockito.`when`(userRepository !!.findById(eq("1")))
.thenReturn(Optional.of(users().get(0)))
Mockito.`when`(userRepository.findById(eq("2"))).thenReturn(Optional.of(users().get(1)))
}
@Test
fun testGetUser() {
this.mockMvc!!.perform(get("/user").param("id", "2"))
.andExpect(MockMvcResultMatchers.status().isOk)
.andExpect(MockMvcResultMatchers.jsonPath("$.username").value(Matchers.equalTo("username1")))
.andExpect(MockMvcResultMatchers.jsonPath("$.remaining_requests").value(Matchers.equalTo(101)))
.andExpect(MockMvcResultMatchers.jsonPath("$.type").value(Matchers.equalTo("USER")))
}
fun users(): List<User> {
val user1 = User("1", "username", "password", "123", 100, UserType.BETA)
val user2 = User("2", "username1", "password1", "1234", 101, UserType.USER)
return arrayListOf<User>(user1, user2)
}
private fun <T> any(type: Class<T>): T {
Mockito.any(type)
return null as T
}
}
问题是它不起作用,因为没有 repositoryBean
可以注入(inject)到 userService
bean 中。
失败并显示
org.mockito.exceptions.misusing.InjectMocksException:
Cannot instantiate @InjectMocks field named 'userService' of type 'class service.UserService'.
You haven't provided the instance at field declaration so I tried to construct the instance.
However the constructor or the initialization block threw an exception : Parameter specified as non-null is null: method service.UserService.<init>, parameter userRepository
模拟存储库层的正确方法是什么?
最佳答案
所以首先,如果这是一个 Web 层/ Controller 测试,您应该模拟 UserSevice
而不是用户存储库。如果这是对 UserSevice
的测试,则不需要 Web 环境。其次,我认为您的代码对于将类型声明为可为空来说非常冗长我会使用 kotlin lateinit专门为这些情况创建的。
说我通常做的是创建一个嵌套的@Configuration
类,其中显式包含我的bean声明。
@RunWith(SpringRunner::class)
@WebMvcTest(UserEndpoints::class)
@Import(TestConfig::class)
class UserEndpointsTest {
}
@Configuration
class TestConfig {
@Bean
fun userRepository(): UserRepository = mock(UserRepository.class)
@Bean
fun userService(UserRepository userRepo): UserService = UserService(userRepo)
}
然后你可以使用简单的@Autowired
注入(inject)你的bean(不需要混合spring和mockito注释)
关于java - Kotlin Spring Boot 测试端点和服务层,并模拟存储库层,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58778859/