Spring 使用 mockito 启动
Spring boot with mockito
我需要用 mocking dao 测试服务方法。而且我还需要测试 dao 方法以了解方法是否有效 correctly.But 我无法将 mockito 与 spring 引导集成。如果我使用 MockitoJUnitRunner
第一个测试有效 如果我使用 SpringJUnit4ClassRunner
第二个测试有效。我也尝试使用 @MockBean
而不是 @Mock
,但它也不起作用。
//SpringJUnit4ClassRunner
//MockitoJUnitRunner
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class BookServiceTests {
@Mock
private BookDao bookDao;
@Autowired
private BookDao bookDao2;
private List<Book> listOfBooks;
@InjectMocks
@Autowired
private BookService bookService;
@PersistenceContext
private EntityManager entityManager;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testGetMostPopularBooksInService() {
fillListOfBooks();
when(bookDao.selectMostPopularBooks(3, 3)).thenReturn(listOfBooks);
assertEquals(3, bookService.getMostPopularBooks(0, 3).size());
}
@Test
@Transactional
public void testSelectMostPopularBooks() {
fillDBByBooks();
List<Book> listOfPopularBooks = bookDao2.selectMostPopularBooks(0, 3);
assertEquals(3, listOfPopularBooks.size());
assertEquals("Марсианинн", listOfPopularBooks.get(0).getName());
}
private void fillListOfBooks() {
Writer writer = new Writer(3, "Джек", "Лондон", "...", null);
listOfBooks = new ArrayList<>();
listOfBooks.add(new Book(6, "Зов предков", 1990, writer, "...",
10, new HashSet<>(Arrays.asList(new Genre(1, "Психология")))));
listOfBooks.add(new Book(8, "Зов предков", 1990, writer, "...",
25, new HashSet<>(Arrays.asList(new Genre(1, "Психология")))));
listOfBooks.add(new Book(10, "Зов предков", 1990, writer, "...",
35, new HashSet<>(Arrays.asList(new Genre(1, "Психология")))));
}
private void fillDBByBooks() {
Writer writer = new Writer(28, null, null, null, null);
entityManager.persist(new Book(0, "Огонь и вода", 1990, writer, "...",
105, new HashSet<>(Arrays.asList(new Genre(1, "Психология")))));
entityManager.persist(new Book(0, "Солнце", 1990, writer, "...",
150, new HashSet<>(Arrays.asList(new Genre(1, "Психология")))));
entityManager.persist(new Book(0, "Космос", 1990, writer, "...",
200, new HashSet<>(Arrays.asList(new Genre(1, "Психология")))));
entityManager.persist(new Book(0, "Марсианин", 1990, writer, "...",
225, new HashSet<>(Arrays.asList(new Genre(1, "Психология")))));
}
}
首先,测试 class 中缺少您的上下文配置注释,因此您不会在那里获得任何 spring 容器支持或自动装配。它应该是这样的:
@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(
classes = {MyApplicationConfig.class}
)
public class MyTestClass
其次,我不会在同一测试中混合模拟 bean 和自动装配的 bean class。我不确定这是否可能。我建议您将测试分成两个 classes。一个具有真实的 DAO 和可用的上下文配置,另一个 class 仅具有纯模拟。
实际上,ContextConfiguration 注释不是强制性的,因为 SpringBootTest 将尝试自行查找现有配置(但据我所知,如果有超过 1 个可用的上下文配置,它将抛出异常)。
此外,使用mock beans和autowired没有问题,这里是一个例子:
@RunWith ( SpringRunner.class )
@SpringBootTest
public class TestClassTest {
@Autowire
private RealBean realBean;
@MockBean
private BeanYouWantToMock mockedBean;
@Override
public void setUp() throws Exception {
MockitoAnnotations.initMocks( this );
}
但是,不要使用@InjectMocks 注释,@MockBean 意味着你正在用模拟的 bean 替换上下文中的真实 bean,所以你不需要将它注入到某个地方, spring 上下文将为您完成。
我需要用 mocking dao 测试服务方法。而且我还需要测试 dao 方法以了解方法是否有效 correctly.But 我无法将 mockito 与 spring 引导集成。如果我使用 MockitoJUnitRunner
第一个测试有效 如果我使用 SpringJUnit4ClassRunner
第二个测试有效。我也尝试使用 @MockBean
而不是 @Mock
,但它也不起作用。
//SpringJUnit4ClassRunner
//MockitoJUnitRunner
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class BookServiceTests {
@Mock
private BookDao bookDao;
@Autowired
private BookDao bookDao2;
private List<Book> listOfBooks;
@InjectMocks
@Autowired
private BookService bookService;
@PersistenceContext
private EntityManager entityManager;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testGetMostPopularBooksInService() {
fillListOfBooks();
when(bookDao.selectMostPopularBooks(3, 3)).thenReturn(listOfBooks);
assertEquals(3, bookService.getMostPopularBooks(0, 3).size());
}
@Test
@Transactional
public void testSelectMostPopularBooks() {
fillDBByBooks();
List<Book> listOfPopularBooks = bookDao2.selectMostPopularBooks(0, 3);
assertEquals(3, listOfPopularBooks.size());
assertEquals("Марсианинн", listOfPopularBooks.get(0).getName());
}
private void fillListOfBooks() {
Writer writer = new Writer(3, "Джек", "Лондон", "...", null);
listOfBooks = new ArrayList<>();
listOfBooks.add(new Book(6, "Зов предков", 1990, writer, "...",
10, new HashSet<>(Arrays.asList(new Genre(1, "Психология")))));
listOfBooks.add(new Book(8, "Зов предков", 1990, writer, "...",
25, new HashSet<>(Arrays.asList(new Genre(1, "Психология")))));
listOfBooks.add(new Book(10, "Зов предков", 1990, writer, "...",
35, new HashSet<>(Arrays.asList(new Genre(1, "Психология")))));
}
private void fillDBByBooks() {
Writer writer = new Writer(28, null, null, null, null);
entityManager.persist(new Book(0, "Огонь и вода", 1990, writer, "...",
105, new HashSet<>(Arrays.asList(new Genre(1, "Психология")))));
entityManager.persist(new Book(0, "Солнце", 1990, writer, "...",
150, new HashSet<>(Arrays.asList(new Genre(1, "Психология")))));
entityManager.persist(new Book(0, "Космос", 1990, writer, "...",
200, new HashSet<>(Arrays.asList(new Genre(1, "Психология")))));
entityManager.persist(new Book(0, "Марсианин", 1990, writer, "...",
225, new HashSet<>(Arrays.asList(new Genre(1, "Психология")))));
}
}
首先,测试 class 中缺少您的上下文配置注释,因此您不会在那里获得任何 spring 容器支持或自动装配。它应该是这样的:
@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(
classes = {MyApplicationConfig.class}
)
public class MyTestClass
其次,我不会在同一测试中混合模拟 bean 和自动装配的 bean class。我不确定这是否可能。我建议您将测试分成两个 classes。一个具有真实的 DAO 和可用的上下文配置,另一个 class 仅具有纯模拟。
实际上,ContextConfiguration 注释不是强制性的,因为 SpringBootTest 将尝试自行查找现有配置(但据我所知,如果有超过 1 个可用的上下文配置,它将抛出异常)。
此外,使用mock beans和autowired没有问题,这里是一个例子:
@RunWith ( SpringRunner.class )
@SpringBootTest
public class TestClassTest {
@Autowire
private RealBean realBean;
@MockBean
private BeanYouWantToMock mockedBean;
@Override
public void setUp() throws Exception {
MockitoAnnotations.initMocks( this );
}
但是,不要使用@InjectMocks 注释,@MockBean 意味着你正在用模拟的 bean 替换上下文中的真实 bean,所以你不需要将它注入到某个地方, spring 上下文将为您完成。