Bài viết Câu hỏi About RongvangIT
profile Pic
0
0

Đăng ngày:

  75 Lượt xem

Sử dụng Mockito-Kotlin để Viết Mã Kiểm thử

KotlinMockito-KotlinMockito

Tôi sẽ tóm tắt cách sử dụng Mockito-Kotlin.

Trong Java và các ngôn ngữ khác, có một thư viện gọi là Mockito để tạo đối tượng giả mạo cho kiểm thử. Trước đây, tôi đã thử nghiệm việc sử dụng Mockito để viết mã kiểm thử cho một ứng dụng mẫu sử dụng Kotlin và Spring Boot. Với sự xuất hiện của thư viện Mockito-Kotlin dành riêng cho Kotlin, tôi đã quyết định viết lại mã kiểm thử sử dụng nó dựa trên ghi chú của mình từ thời điểm trước đó.

Mã nguồn cần kiểm thử

@Service
class UserService {
    @Autowired
    lateinit var repository: UserRepository

    fun getUserById(id: Int): User? {
        return repository.findById(id).orElse(null)
    }
}

Lớp này phụ thuộc vào lớp UserRepository sau đây để thực hiện truy cập cơ sở dữ liệu bằng cách sử dụng các phiên bản JPA repository. (Khi bạn muốn tự tạo một lớp cho kiểm thử, bạn sẽ phải ghi đè nhiều phương thức, điều này khá phức tạp.)

@Repository
interface UserRepository: JpaRepository<User, Int> {}

Chúng ta chỉ muốn kiểm thử UserService, vì vậy chúng ta muốn giả mạo UserRepository.

Sử dụng Mockito-Kotlin

Thêm phụ thuộc sau vào build.gradle:

testImplementation 'org.mockito.kotlin:mockito-kotlin:5.2.0'

Tạo lớp kiểm thử

class UserServiceTestByKotlin {
    @Mock
    lateinit var mockUserRepository: UserRepository

    @InjectMocks
    lateinit var userService: UserService

    @BeforeEach
    fun init() {
        MockitoAnnotations.openMocks(this)
    }
}

Sử dụng @Mock để chỉ định lớp cần được giả mạo. Sử dụng @InjectMocks để chỉ định lớp chịu ảnh hưởng từ lớp giả mạo.

Kiểm thử sử dụng giả mạo

@Test
fun shouldInvokeFindById() {
    userService.getUserById(10)
    userService.getUserById(20)
    userService.getUserById(20)

    verify(mockUserRepository).findById(10)    ///(1)
    verify(mockUserRepository, atLeast(1)).findById(10)

    verify(mockUserRepository, times(3)).findById(anyInt())
}

Sử dụng verify() để kiểm thử số lần phương thức được gọi. Số lần cụ thể hoặc số lần tối thiểu/tối đa có thể được chỉ định trong đối số thứ hai. ///(1) tương đương với việc truyền times(1) trong đối số thứ hai.

Kiểm thử sử dụng đối tượng giả mạo

private val testUser = User(1, "taro", 33)

@Test
fun shouldReturnUserDetailFromRepository() {
    whenever(mockUserRepository.findById(1))
        .thenReturn(Optional.of(testUser))

    val user = userService.getUserById(1)
    assertThat(user!!.id).isEqualTo(1)
    assertThat(user.userName).isEqualTo("taro")
    assertThat(user.age).isEqualTo(33)
}

Sử dụng whenever()thenReturn() để cài đặt đối tượng giả mạo. Nếu không có giá trị trả về được chỉ định, giá trị sẽ là null (hoặc giá trị khởi tạo cho kiểu nguyên thủy).

@Test
fun stubDefaultValue() {
    val user = userService.getUserById(2)
    assertThat(user).isNull()
}

Có thể viết ngắn gọn hơn như sau:

mockUserRepository.stub {
    on { findById(1) } doReturn Optional.of(testUser)
}

Sự khác biệt khi sử dụng Mockito trong Java

whenwhenever

Khi cài đặt giá trị trả về trong mock, trong Mockito, ta sử dụng when. Tuy nhiên, với Kotlin, when là từ khoá đã được sử dụng rồi, vì vậy ta sử dụng whenever. Thực chất, nếu bạn xem vào nguồn mã, bạn sẽ thấy rằng nó chỉ là một cú pháp ngắn gọn cho when.

any()

whenever(mock.example(any(User::class.java))).thenReturn(11)

Hoặc

verify(mock).example(any

(User::class.java))

Một trong 2 cách trên sẽ tạo ra NullPointerException.

Tuy đã có người nói rằng “Bạn có thể sử dụng any()!”, nhưng tôi tự hỏi liệu điều này có đúng ko?

Trong Project Spring Boot chúng ta có thể Implementation như dưới.

testImplementation 'org.springframework.boot:spring-boot-starter-test'

Ở phần Implementation trên có bao gồm package Mockito và có vẻ Mockito và Mockito-Kotlin có cùng any().

Tôi nhận thức rằng any() được sử dụng trong mã nguồn, nhưng nó đến từ Mockito, không phải từ Mockito-Kotlin. Điều này đã gây ra xung đột khi tôi sử dụng nó. (Do đó, IDE đã hiển thị lỗi nếu tôi không truyền đối số.)

whenever(mockUserRepository.example(org.mockito.kotlin.any())).thenReturn(11)
mockUserRepository.example(testUser)
verify(mockUserRepository).example(org.mockito.kotlin.any())

Và cách sửa, dòng mã trên sẽ hoạt động nếu bạn chỉ định rõ tên gói.

Kết luận

Trên đây tôi đã tóm tắt cách Sử dụng Mockito-Kotlin để Viết Mã Kiểm thử rồi. Hi vọng nó sẽ có ích cho công việc của anh em. Chào thân ái và quyết thắng

dev_pro_it
Đang làm IT tại Japan

Bình luận

Bài viết chưa có bình luận. Hãy trở thành người bình luận đầu tiên!
Sign up for free and join this conversation.
Sign Up
If you already have a RongvangIT account Login
Danh sách thư mục
Bắt đầu ngay với RồngVàngIT - nền tảng chia sẻ kiến thức lập trình tuyệt vời cho kỹ sư Việt Nam!

Hãy đăng nhập để sử dụng hàng loạt các chức năng tuyệt vời của RồngVàngIT !

  1. 1. Bạn sẽ nhận được các bài viết phù hợp bằng chức năng theo dõi tag và người dùng.
  2. 2. Bạn có thể đọc lại các thông tin hữu ích bằng chức năng lưu trữ nội dung.
  3. 3. Chia sẻ kiến thức, đặt câu hỏi và ghi lại quá trình trưởng thành của mình cùng RồngVàngIT !
Tạo tài khoản Đăng nhập
profile Pic