当需要测试的接口依赖多个其他的接口时,我们依旧可以使用Mockito来进行处理。这时候,我们通常会使用到Mockito的@InjectMocks
和@Mock
注解。
下面提供一个例子,这个例子描述了一个BookService类,它依赖于另外两个接口:BookRepository和UserRepository:
public class BookService {private final BookRepository bookRepository;private final UserRepository userRepository;public BookService(BookRepository bookRepository, UserRepository userRepository) {this.bookRepository = bookRepository;this.userRepository = userRepository;}public Book lendBook(int bookId, int userId) {Optional<User> user = userRepository.findById(userId);Optional<Book> book = bookRepository.findById(bookId);if (book.isPresent() && user.isPresent()) {book.get().setUser(user.get());return bookRepository.save(book.get());}throw new RuntimeException("Book or User not found");}
}
在测试该BookService类时,我们需要mock掉BookRepository和UserRepository接口,并模拟它们的行为:
@RunWith(MockitoJUnitRunner.class)
public class BookServiceTest {@InjectMocksprivate BookService bookService;@Mockprivate BookRepository bookRepository;@Mockprivate UserRepository userRepository;@Testpublic void testLendBook() {User user = new User(1, "John");Book book = new Book(1, "A Tale of Two Cities", null);when(userRepository.findById(1)).thenReturn(Optional.of(user));when(bookRepository.findById(1)).thenReturn(Optional.of(book));when(bookRepository.save(book)).thenReturn(book);Book result = bookService.lendBook(1, 1);assertEquals(user, result.getUser());}
}
在上面的测试案例中,@InjectMocks
注解被用于创建BookService的实例,同时将由@Mock
注解创建的mock对象自动注入到BookService实例中。针对UserRepository和BookRepository的模拟行为被定义在when函数调用中。
这样我们就可以在没有真实数据库环境的情况下,通过模拟预期行为来对BookService进行单元测试了。