UnitTestBot / UTBotJava

Automated unit test generation and precise code analysis for Java
Apache License 2.0
137 stars 44 forks source link

Spring integration test fails on `entityManager.flush()` before call to method under test #2628

Open IlyaMuravjov opened 1 year ago

IlyaMuravjov commented 1 year ago

Description

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.

To Reproduce

Generate integration tests for UserController.getContacts() from Medical-Web-App/develop-new project with MedicalWebApp 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 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\":[]}"));
}