2

None of these solutions helped here: Spring mockMvc doesn't consider validation in my test. Added all of these dependencies, nothing helps.

I use Spring Boot 2.1.2, pom.xml:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.2.RELEASE</version>
</parent>
<properties>
    <java.version>1.8</java.version>
</properties>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>runtime</scope>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-hateoas</artifactId>
    </dependency>

    <!-- Testing -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>com.github.springtestdbunit</groupId>
        <artifactId>spring-test-dbunit</artifactId>
        <version>1.3.0</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.dbunit</groupId>
        <artifactId>dbunit</artifactId>
        <version>2.5.4</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>com.jcabi</groupId>
        <artifactId>jcabi-matchers</artifactId>
        <version>1.3</version>
        <scope>test</scope>
    </dependency>

</dependencies>

I use standard hibernate validation '@NotNull':

@Entity
@Table(name="employee")
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class Employee  {

    @Id
    @Column
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    protected Long id;

    @NotNull(message = "Please provide name")
    @Column(name = "name")
    private String name;

    @Column(name = "role")
    private String role;

    public Employee() {}

    public Employee(String name, String role) {
        this.name = name;
        this.role = role;
    }
}

@RestController
@RequestMapping(EmployeeController.PATH)
public class EmployeeController {

    public final static String PATH = "/employees";

    @Autowired
    private EmployeeService service;

    @PostMapping("")
    public Employee newEmployee(@RequestBody @Valid Employee newEmployee) {
        return service.save(newEmployee);
    }
}

@Service
public class EmployeeService {

    @Autowired
    private EmployeeRepository repository;

    public Employee save(Employee entity) {
        return getRepository().save(entity);
    }
}

@Repository
public interface EmployeeRepository extends JpaRepository<Employee, Long> {

}

Then I test my controller:

@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
@DatabaseSetup("/employee.xml")
@TestExecutionListeners({
        TransactionalTestExecutionListener.class,
        DependencyInjectionTestExecutionListener.class,
        DbUnitTestExecutionListener.class
})
public class EmployeeControllerWebApplicationTest {

    @Autowired
    private WebApplicationContext context;

    private MockMvc mockMvc;
    private static String employeeRouteWithParam = EmployeeController.PATH + "/{id}";

    @Before
    public void setup() {
        mockMvc = MockMvcBuilders
                .webAppContextSetup(context)
                .build();
    }

    @Test
    public void create_WithoutName_ShouldThrowException() throws Exception {
        String role = "admin";
        Employee expectedEmployee = new Employee(null, role);

        ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
        String json = ow.writeValueAsString(expectedEmployee);

        ResultActions resultActions = this.mockMvc.perform(post(PATH)
                .contentType(MediaType.APPLICATION_JSON_UTF8)
                .content(json))
                .andDo(print());

        String contentAsString = resultActions.andReturn().getResponse().getContentAsString();
        System.out.println("content: " + contentAsString); // empty body

        resultActions
                .andExpect(status().isBadRequest())
                .andExpect(jsonPath("error").exists())      // not exist!!!
                .andExpect(jsonPath("timestamp").exists()); // not exist!!!

    }
}

employee.xml:

<dataset>
    <Employee id="1" name="John" role="admin"/>
    <Employee id="2" name="Mike" role="user"/>
</dataset>

I can not understand why it does not work when I test through @MockMvc. What am i doing wrong? Status is correct, but there is no error content, empty response

But validation works if tested on a really running application, then everything works.

FreeOnGoo
  • 868
  • 1
  • 8
  • 26
  • Can you update your question so that it is complete? The `ID` and `EmployeeRepository` classes are missing at the moment. The `PATH` constant is also missing in your tests as well as the `employee.xml` file. – Andy Wilkinson Mar 11 '19 at 09:53
  • If I try to fill in the pieces missing from your example, the call to the controller fails with a `MethodArgumentNotValidException` with the message `Please provide name`. – Andy Wilkinson Mar 11 '19 at 09:59
  • @AndyWilkinson you can see the whole project on my github https://github.com/Freeongoo/spring-examples/blob/master/rest-jpa-validation/src/test/java/hello/controller/beanValidation/EmployeeControllerTest.java – FreeOnGoo Mar 11 '19 at 13:28
  • @AndyWilkinson I added the requested modifications in the code – FreeOnGoo Mar 11 '19 at 17:26
  • @AndyWilkinson and please tell me, did you run a line in your example code: .andExpect(jsonPath("error").exists())? – FreeOnGoo Mar 11 '19 at 17:41
  • 1
    The reponse is being validated and an exception is being thrown in your example. Your test is failing because you're really trying to test Spring Boot error infrastructure rather than your own controller. If you want to include the error infrastructure in your test, you should start a test with a complete web environment and use `TestRestTemplate` rather than `MockMvc`. – Andy Wilkinson Mar 11 '19 at 20:14
  • @AndyWilkinson but this is strange. Since interception of errors through `@ControllerAdvice` works correctly, why the same is not done for `@Valid` – FreeOnGoo Mar 11 '19 at 20:32

0 Answers0