Spring integration test fails with org.hibernate.TransientObjectException on entityManager.flush() before call to method under test.
We need to consider executing entityManager.flush() during concrete execution, also if @Transactional is used we should also probably call entityManager.flush() before and after method under test to ensure database is kept in the consistent state.
No test fails with exception before reaching method under test call.
Actual behavior
There's a test that fails with org.hibernate.TransientObjectException on entityManager.flush() before call to method under test.
Visual proofs (screenshots, logs, images)
java.lang.IllegalStateException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.app.medicalwebapp.model.Topic
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:151)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1406)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1389)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:311)
at com.sun.proxy.$Proxy129.flush(Unknown Source)
at com.app.medicalwebapp.controllers.UserControllerTest.testGetContactsWithBlankString(UserControllerTest.java:479)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:57)
at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55)
Caused by: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.app.medicalwebapp.model.Topic
at org.hibernate.engine.internal.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:347)
at org.hibernate.type.EntityType.getIdentifier(EntityType.java:507)
at org.hibernate.type.EntityType.nullSafeSet(EntityType.java:280)
at org.hibernate.persister.collection.AbstractCollectionPersister.writeElement(AbstractCollectionPersister.java:925)
at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:1347)
at org.hibernate.action.internal.CollectionRecreateAction.execute(CollectionRecreateAction.java:50)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:604)
at org.hibernate.engine.spi.ActionQueue.lambda$executeActions$1(ActionQueue.java:478)
at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:684)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:475)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:344)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:40)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1402)
... 77 more
@Test
@DisplayName("getContacts: currentUserUsername = '\n\t\r'")
public void testGetContactsWithBlankString() throws Exception {
Topic topic = new Topic();
User creator = new User();
creator.setLastname("XZ");
creator.setRole("-3");
creator.setRegisteredDate(null);
creator.setStatus(-1);
byte[] avatar = {(byte) 0, (byte) 0, Byte.MAX_VALUE};
creator.setAvatar(avatar);
creator.setRate(-1);
creator.setPatronymic("#$\\\"'");
creator.setPassword("10");
creator.setUsername("");
Active active = Active.OFFLINE;
creator.setActive(active);
entityManager.persist(creator);
entityManager.flush();
topic.setCreator(creator);
topic.setCreationTime(null);
topic.setName("\n\t\r");
entityManager.persist(topic);
entityManager.flush();
ChatFile chatFile = new ChatFile();
FileObjectFormat format = FileObjectFormat.JPEG;
chatFile.setFormat(format);
chatFile.setFileName("10");
byte[] fileContent = {Byte.MAX_VALUE, (byte) -1, (byte) -1};
chatFile.setFileContent(fileContent);
entityManager.persist(chatFile);
entityManager.flush();
Contact contact = new Contact();
LinkedList contactsList = new LinkedList();
User user = new User();
user.setRate(Integer.MIN_VALUE);
user.setRegisteredDate(null);
user.setUsername("-3");
byte[] avatar1 = {};
user.setAvatar(avatar1);
user.setPassword("-3");
Active active1 = Active.ONLINE;
user.setActive(active1);
user.setLastname("abc");
user.setFirstname("10");
user.setPatronymic("");
user.setInitials("\n\t\r");
entityManager.persist(user);
entityManager.flush();
contactsList.add(user);
contact.setContactsList(contactsList);
contact.setContactsOwner("#$\\\"'");
entityManager.persist(contact);
entityManager.flush();
Record record = new Record();
record.setParent(Long.MAX_VALUE);
Set attachments = emptySet();
record.setAttachments(attachments);
record.setContent("-3");
record.setCreationTime(null);
User creator1 = new User();
creator1.setRole("10");
creator1.setInitials("#$\\\"'");
creator1.setFirstname("");
creator1.setUsername("#$\\\"'");
creator1.setRate(-1);
creator1.setPassword("10");
creator1.setActive(active);
creator1.setPatronymic("XZ");
creator1.setStatus(0);
creator1.setRegisteredDate(null);
entityManager.persist(creator1);
entityManager.flush();
record.setCreator(creator1);
HashSet topics = new HashSet();
Topic topic1 = new Topic();
topic1.setCreator(null);
topic1.setName("#$\\\"'");
topic1.setCreationTime(null);
topics.add(topic1);
Topic topic2 = new Topic();
topic2.setCreator(null);
topic2.setName("");
topic2.setCreationTime(null);
topics.add(topic2);
Topic topic3 = new Topic();
topic3.setCreationTime(null);
topic3.setName("-3");
topic3.setCreator(null);
topics.add(topic3);
record.setTopics(topics);
record.setEdited(false);
record.setTitle("abc");
record.setNumberOfReplies(0);
entityManager.persist(record);
entityManager.flush(); // <--------------------------------------- this flush() fails
ChatMessage chatMessage = new ChatMessage();
ArrayList attachments1 = new ArrayList();
FileObject fileObject = new FileObject();
fileObject.setUID("abc");
fileObject.setInitialName("\n\t\r");
fileObject.setPathToFile("XZ");
fileObject.setOwner(0L);
fileObject.setCreationTime(null);
fileObject.setSize(Integer.MIN_VALUE);
fileObject.setDownloadLink("10");
FileObjectFormat format1 = FileObjectFormat.PDF;
fileObject.setFormat(format1);
entityManager.persist(fileObject);
entityManager.flush();
attachments1.add(fileObject);
FileObject fileObject1 = new FileObject();
fileObject1.setFormat(format);
fileObject1.setUID("\n\t\r");
fileObject1.setDownloadLink("\n\t\r");
fileObject1.setCreationTime(null);
fileObject1.setOwner(null);
fileObject1.setPathToFile("");
fileObject1.setInitialName("10");
fileObject1.setSize(0);
entityManager.persist(fileObject1);
entityManager.flush();
attachments1.add(fileObject1);
FileObject fileObject2 = new FileObject();
fileObject2.setInitialName("-3");
fileObject2.setCreationTime(null);
fileObject2.setUID("\n\t\r");
fileObject2.setDownloadLink("XZ");
fileObject2.setSize(-1);
fileObject2.setOwner(4294967295L);
fileObject2.setPathToFile("XZ");
fileObject2.setFormat(format1);
entityManager.persist(fileObject2);
entityManager.flush();
attachments1.add(fileObject2);
chatMessage.setAttachments(attachments1);
chatMessage.setSenderId(0L);
StatusMessage statusMessage = StatusMessage.UNREAD;
chatMessage.setStatusMessage(statusMessage);
chatMessage.setChatId("abc");
chatMessage.setContent("10");
chatMessage.setSenderName("\n\t\r");
chatMessage.setSendDate(null);
List dataFilesDicom = emptyList();
chatMessage.setDataFilesDicom(dataFilesDicom);
chatMessage.setRecipientId(Long.MAX_VALUE);
List uidFilesDicom = emptyList();
chatMessage.setUidFilesDicom(uidFilesDicom);
entityManager.persist(chatMessage);
entityManager.flush();
User user1 = new User();
byte[] avatar2 = {(byte) 1, (byte) -1};
user1.setAvatar(avatar2);
user1.setRole("#$\\\"'");
user1.setActive(active1);
user1.setRegisteredDate(null);
user1.setStatus(-1);
user1.setPassword("10");
user1.setInitials("10");
user1.setLastname("10");
user1.setPatronymic("");
user1.setUsername("-3");
entityManager.persist(user1);
entityManager.flush();
FileObject fileObject3 = new FileObject();
fileObject3.setInitialName("");
fileObject3.setUID("#$\\\"'\u008B");
fileObject3.setSize(0);
fileObject3.setCreationTime(null);
fileObject3.setOwner(0L);
FileObjectFormat format2 = FileObjectFormat.PNG;
fileObject3.setFormat(format2);
fileObject3.setPathToFile("#$\\\"'");
fileObject3.setDownloadLink("10");
entityManager.persist(fileObject3);
entityManager.flush();
UriComponentsBuilder uriComponentsBuilder = fromPath("/api/search/contacts");
Object[] values = {"\n\t\r"};
UriComponentsBuilder uriComponentsBuilder1 = uriComponentsBuilder.queryParam("currentUserUsername", values);
String urlTemplate = uriComponentsBuilder1.toUriString();
Object[] uriVars = {};
MockHttpServletRequestBuilder mockHttpServletRequestBuilder = get(urlTemplate, uriVars);
ResultActions actual = mockMvc.perform(mockHttpServletRequestBuilder);
actual.andDo(print());
actual.andExpect((status()).is(200));
actual.andExpect((content()).string("{\"contactWithLastMsg\":[]}"));
}
Description
Spring integration test fails with
org.hibernate.TransientObjectException
onentityManager.flush()
before call to method under test.We need to consider executing
entityManager.flush()
during concrete execution, also if@Transactional
is used we should also probably callentityManager.flush()
before and after method under test to ensure database is kept in the consistent state.To Reproduce
Generate integration tests for
UserController.getContacts()
fromMedical-Web-App/develop-new
project withMedicalWebApp
configuration.Environment
Setup environment as described in the Local Development section of the
Medical-Web-App
project README.Expected behavior
No test fails with exception before reaching method under test call.
Actual behavior
There's a test that fails with
org.hibernate.TransientObjectException
onentityManager.flush()
before call to method under test.Visual proofs (screenshots, logs, images)