Monday, September 20, 2021

Difference between @WebMvcTest and @DataJpaTest in Spring Boot? Example

Hello guys, testing the Spring Boot application is very important but not many developers pay attention to that. If you are learning how to test the Spring Boot application and wondering what is @WebMvcTest and @DataJpaTest and how to use them then you have come to the right place. Earlier, I have shared 20+ Spring Boot Testing interview questions and in this article, I will teach you how to use @DataJpaTest and @WebMvcTest annotation with real-world examples.  Spring Boot is an evolution of the Spring framework which helps to create both stand-alone and spring-based applications with minimal cost. 

This tutorial shows the difference between @WebMvcTest and @DataJpaTest as having the knowledge of how things working within a programming language, makes you a good programmer. 

So before going to a discussion about the difference between @WebMvcTest and @DataJpaTest, let’s have a quick introduction of what are these testing methods and what is there usage? 

By the way, if you are new to Spring Boot and Spring Data JPA then also recommend you to check out these best Spring Boot courses and Spring Data JPA courses to learn these in-demand frameworks and libraries from scratch. I have shared hands-on practica courses on those articles which is suitable for both beginners and experienced Java developers. 




1. What is @DataJpaTest in Spring Boot? Example

The @DataJpaTest annotation in Spring Boot is used to test the persistence layer components that autoconfigure in-memory embedded databases and look for @Entity classes and Spring Data JPA repositories.

The @DataJpaTest is used to test JPA repositories and used with the @RunWith(SpringRunner.class). With the @DataJpaTest annotation, Spring Boot provides a convenient way to set up an environment with an embedded database to test our database queries against. So have a look into this using the example given below.

So in here, created a StudentRepository, a Jpa repository which is annotated with @Repository that allows being discovered and registered with the application context.

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface StudentRepository extends JpaRepository < Student, Long > {
    //queries in here
}


Now using @DataJpaTest annotation which is used to disable full auto-configuration and instead apply only configuration relevant to Jpa Tests.

The tests that are annotated with @DataJpaTest can be roll-backed and also they are transactional. Some other core features seen on @DataJpaTest annotation are,

Scans for @Entity classes and configures Spring Data JPA repositories annotated with @Repository annotation. This allows you to test domain logic so you can check JPA mappings and you can check queries

It also configures Hibernate, Spring Data JPA, and an in-memory database. You can override the in-memory database if you want to reuse a real one.

It also gives you access to a bean called TestEntityManager. This is a replacement for the standard entity manager that just provides a few handy methods that you'll frequently use in your tests.

It is also transactional and rollback at the end of each test. If we wanna disable transaction management, we can use:

@Transactional(propagation = Propagation.NOT_SUPPORTED)

Can also inject a TestEntityManager bean specially designed for tests which is an alternative to JPA EntityManager.

@Autowired
private TestEntityManager entityManager;

The StudentRepositoryTest class tests the StudentRepository, which is of type JpaRepository and is used to store and retrieve Student instances from underlying databases, as seen in the example below.

import org.junit.Assert;
import org.junit.Test;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;

@RunWith(SpringRunner.class)
@DataJpaTest
public class StudentRepoTest {
    @Autowired
    StudentRepository studentRepository;

    @Test
    public void testRepository() {
        Student st = new Student();
        st.setStudentId(15321);
        st.setStudentName("James");
        st.setStudentAge(16);

        studentRepository.save(st);

        Assert.assertNotNull(st.getId());
    }
}

So after running this test case, you will find the JPA-related configuration has been loaded into context and then test case execution starts.  So let's have a look at other test methods, @WebMvcTest annotation in Spring Boot. 




2. What is @WebMvcTest Annotation in Spring Framework? Example

The @WebMvcTest is used in combination with @RunWith(SpringRunner.class) when a test focuses only on Spring MVC components. It disable entire auto-configuration (not @Component, @Service, or @Repository beans) and only use configuration related to MVC tests like @Controller and @ControllerAdvice instead.

Auto-configure Spring Security and MockMvc

So let’s have a quick view of how @WebMvcTest works in a program. Create a SpringRestController class which is used to have tested using @WebMvcTest on other classes.


@RestController
public class SpringRestController {

    @ResponseBody
    @GetMapping("/helloworld")
    public String helloworld() {
        return "Hello World";
    }
}

In the above Rest controller method, you have used only one method with GET request and it returns the Hello World in the response body of the request.

Create a Junit class to test the controller and REST controller using the @WebMvcTest annotation. In the classes below, we've used the @WebMvcTest annotation in conjunction with the controller or REST controller class that we want to test.

@WebMvcTest(SpringRestController.class)
public class SpringRestControllerTesting {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void shouldReturnDefaultMessage() throws Exception {
        mockMvc.perform(MockMvcRequestBuilders.get("/helloworld"))
            .andDo(MockMvcResultHandlers.print())
            .andExpect(MockMvcResultMatchers.status().isOk())
            .andExpect(MockMvcResultMatchers.content()
                       .string(Matchers.containsString("Hello World")));
    }

}



So this is how we can use the @WebMvcTest to test our Spring Boot applications. You will run the above code snippet in your application and have a good understanding of how things work in @WebMvcTest.




Difference between @WebMvcTest and @DataJpaTest?

Here are some of the core differences between @WebMvcTest and @DataJpaTest are given below.

1. The @WebMvcTest only loads the web layer, which contains security, filters, interceptors, and other requests/response handling components. Tests for methods under @Controller or @RestController are typically written. On the other hand, @DataJpaTest loads only configuration for JPA. It uses an embedded in-memory H2 if not specified otherwise.

2. When compared to @DataJpaTest, annotations like @WebMvcTest keeps your tests more modularized and slightly faster. As previously mentioned, there are a variety of uses for @WebMvcTest and @DataJpaTest. The good practice here is to use @WebMvcTest to test the controller and mock any dependencies from other layers.

What are @WebMvcTest and @DataJpaTest in Spring Boot? Example and Differences

 


That's all about the difference between @WebMvcTest and @DataJPATest annotation in Spring Boot and Spring Data JPA. As a summary, We need the ability to design a schema and populate it with data in order to test database queries. Because tests should be self-contained, it's better to do this for each one separately. So that’s all about the difference between @WebMvcTest and @DataJpaTest. Hope you enjoy it and see you in the next tutorial.

       Other Spring Framework articles you may like to explore 

    Thanks for reading this article so far. If you find this Spring Boot Testing tutorial and @WebMvcTest and @DataJpaTest example useful, please share them with your friends and colleagues. If you have any questions or feedback, then please drop a note.   

    No comments:

    Post a Comment