Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
259 views
in Technique[技术] by (71.8m points)

java - What is the cause of LazyInitializationException when testing Spring Boot web app with MockMvc and AutoConfigureMockMvc

I am trying out a few examples of unit testing Spring Boot MVC from this tutorial - https://spring.io/guides/gs/testing-web/. My project has Spring Boot MVC and JPA (https://github.com/shankarps/SfgUdemyRecipes)

The Controller that is tested retrieves a list of Recipe entities which have many-to-many mapping with Category entities.

@RequestMapping({"", "/", "/index"})
public String getIndexPage(Model model){
    log.info("Getting all recipes");
    model.addAttribute("recipes", recipeService.getAllRecipes());
    return "index";
}

This Controller works when the Spring Boot app is launched. The list of recipes are shown in the browser.

This test case with SpringBootTest and TestRestTemplate works as expected.

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class IndexControllerHttpTest {
    @LocalServerPort
    private int port;

    @Autowired
    private TestRestTemplate restTemplate;

    @Test
    public void testIndexUrl(){
        String response = this.restTemplate.getForObject("http://localhost:"+port+"/", String.class);
    }
}

However, when I run a test case with MockMVC to test the Controller as a MVC object (with @AutoConfigureMockMvc), without the Http server, I get org.hibernate.LazyInitializationException Exception.

@SpringBootTest
@AutoConfigureMockMvc
public class IndexControllerMockMVCTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void testIndexControllerView() throws Exception {
        this.mockMvc.perform(MockMvcRequestBuilders.get("/")).andExpect(status().isOk());
    }
}

Here is the exception stack trace in full:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.shankar.sfg.recipes.recipes.domain.Category.recipes, could not initialize proxy - no Session    
    at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:606)
    at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:218)
    at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:585)
    at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:149)
    at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:327)
    at java.lang.String.valueOf(String.java:2994)

This looks like an issue with transaction scope. Can anyone help find the root cause? What additional configuration is needed to test the Spring application context when tested as a complete Web application (with @SpringBootTest), versus testing at the MVC layer (@SpringBootTest and @AutoConfigureMockMvc)?

question from:https://stackoverflow.com/questions/65930196/what-is-the-cause-of-lazyinitializationexception-when-testing-spring-boot-web-ap

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The solution was to add @Transactional to the Test method that called the Mock MVC.

@Test
@Transactional
public void testIndexControllerView() throws Exception {
    this.mockMvc.perform(MockMvcRequestBuilders.get("/")).andExpect(status().isOk());
}

This answer deals with similar issue for unit testing a JPA repository object.

LazyInitializationException: could not initialize proxy - no Session

I am not yet sure why a transaction scope is needed when testing the controller without the HTTP server.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...