java - Kotlin Spring Boot 测试端点和服务层,并模拟存储库层

标签 java spring kotlin mocking

为了测试端点,我将 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/

相关文章:

java - 使用自定义外部表单和 Spring Security 进行 CAS 身份验证

android - 不能在 Kotlin 中使用 BindingAdapter

java - 使用 Java 更新 MongoDB 中的特定字段而不是整个文档

java - 如何检查源代码中是否存在禁用词 extGWT

java - 有可能知道 HttpURLConnection 何时建立?

java - 使用 Jsoup 解析表 html

java - 如何向 Spring Boot 应用程序添加日志记录属性

java - Spring Data Elasticsearch将Elasticsearch聚合查询转换为代码

android - ViewModel中的LiveData类型不匹配

Kotlin 集合 : Subtracting two nullable list give incorrect result