因此,我正在运行 @DataJpaTest ,并在我的 setUp 函数中执行entityManager.clear(),最终将书籍对象与持久性上下文分离。但以下测试最终因错误而失败。
BookRepositoryTest > doSomething() FAILED
org.opentest4j.AssertionFailedError: expected: <Book(id=6, title=Pride and Prejudice, price=16.99, quantity=12, author=Jane Austen, ISBN=890-1234567890, genre=Romance, publishDate=1813-01-28)> but was: <Book(id=6, title=Pride and Prejudice, price=16.99, quantity=12, author=Jane Austen, ISBN=890-1234567890, genre=Romance, publishDate=1813-01-27)>
at app//org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:151)
at app//org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:132)
at app//org.junit.jupiter.api.AssertEquals.failNotEqual(AssertEquals.java:197)
at app//org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:182)
at app//org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:177)
at app//org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:1145)
at app//library.backend.api.BookRepositoryTest.doSomething(BookRepositoryTest.java:55)
但是当我注释掉entityManager.clear()行时,测试就通过了。 任何人都知道为什么会发生这种情况?我没有对任何书籍进行任何更改,那么为什么从数据库读取时日期会发生变化?
@ExtendWith(SpringExtension.class)
@DataJpaTest
@ActiveProfiles(profiles = {"test"})
public class BookRepositoryTest {
@Autowired
private BookRepository bookRepository;
@Autowired
private TestEntityManager entityManager;
private ObjectMapper mapper;
@Value("classpath:books.json")
Resource booksJson;
List<Book> books;
@BeforeEach
void setUp() throws Exception{
mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
books = mapper.readValue(booksJson.getInputStream(),
new TypeReference<List<Book>>(){});
books.forEach(entityManager::persistAndFlush);
entityManager.clear();
}
@Test
void doSomething(){
List<Book> firstSixBooks = bookRepository.findAll(PageRequest.of(0,6)).toList();
assertEquals(6, firstSixBooks.size());
for(int j=0; j<6; j++){
assertEquals(books.get(j), firstSixBooks.get(j));
}
}
}
如有任何帮助或建议,我们将不胜感激!
即使使用entityManager.clear(),我也期望测试能够通过,但最终失败了,出于好奇,我想知道为什么。
即使使用entityManager.clear(),我也期望测试能够通过,但最终失败了,出于好奇,我想知道为什么。
当您使用
EntityManager
持久化实体对象时,该对象本身就会变得持久化。除其他外,这意味着该对象由 EntityManager
缓存。这也许是区分持久实体和分离实体的主要因素。
当
EntityManager
被请求提供已缓存的实体时,它会提供缓存的实例本身,而不是副本。当您不分离实体时,这就是您的测试中发生的情况。在这种情况下,您正在测试对象是否是 equals()
本身,这对于任何没有反常的、不合格的 Object
方法的 equals(Object)
来说都是如此。那么,equals()
测试通过也就不足为奇了。
但是,如果您do分离实体,例如通过
clear()
ing EntityManager
,那么当您请求它们时,它必须实例化新实体。在这种情况下,您可以比较具有相同属性值的不同对象。当且仅当您为实体类提供了产生该结果的 equals(Object)
方法时,它们才会比较相等。从 Object
继承的不会产生该结果。
特别是对于实体来说,是否应该为类配备这样的
equals()
方法是有争议的。但是,如果您决定这样做,那么您应该确保也实现兼容的 hashCode()
方法。
IMO,您的测试夹具应该清除
EntityManager
。如果您决定为 Book
类提供与您想要测试的条件相对应的 equals()
方法,那么这应该足以使您现有的测试通过。否则,您应该修改测试,以便它评估您想要检查的任何平等感。例如,这可能意味着比较一个或多个单独的字段。