MockMvc Module

RECORDO

The Recordo MockMvc module empowers developers to streamline the testing of controllers using the MockMvc framework, offering two powerful mechanisms for testing flexibility:

API Client Interfaces

Test Parameters

API Client Interfaces

Developers can define an interface where they specify the API endpoints they want to test using standard Spring annotations. This intuitive approach simplifies the testing process, as Recordo handles the underlying logic. Developers only need to autowire this interface in their test classes.

Example Interface

@RecordoApiClient(interceptors = AuthInterceptor.class)
@RequestMapping("/users")
public interface UserApiClient {

    @GetMapping("/{id}")
    UserDto findById(@PathVariable int id);
    
    @GetMapping("/{id}")
    @ResponseStatus(HttpStatus.NOT_FOUND)
    ErrorDto findById_NotFound(@PathVariable int id);
    
    @GetMapping
    Page<UserDto> findAll(@RequestParam("q") String query, Pageable pageable);
    
    @PostMapping("/{id}/pic")
    void uploadPic(@PathVariable int id, @RequestParam Request.File file);
    
    @PostMapping
    UserDto create(@RequestBody UserDto userDto);
    
    @DeleteMapping("/{id}")
    void delete(@PathVariable int id);
}

Usage Examples

@ExtendWith(RecordoExtension.class)
@WebMvcTest(UserController.class)
class UserControllerTest {

    @Autowired
    private UserApiClient apiClient;

    @Test
    void should_find_by_id() {
        // ...
        UserDto user = apiClient.findById(1L);
        // ...
    }
    
    @Test
    void should_get_not_found_error() {
        // ...
        ErrorDto error = apiClient.findById_NotFound(1L);
        // ...
    }
    
    @Test
    void should_find_all() {
        // ...
        PageRequest pageRequest = PageRequest.of(0, 20, Sort.by(asc("name")));
        Page<UserDto> users = apiClient.findAll("john", pageRequest);
        // ...
    }
    
    @Test
    void should_create_user(
        @Read("/users/new_user.json") UserDto newUser
    ) {
        // ...
        UserDto createdUser = apiClient.create(newUser);
        // ...
    }
    
    @Test
    void should_upload_pic() {
        // ...      
        Request.File file =  Request.File.builder()
            .name("pic.png")
            .content(fileBytes)
            .build();
            
        apiClient.uploadPic(1L, file);
        // ...
    }
    
}

Test Parameters

Developers can declare necessary requests directly as parameters in their test methods, specifying the HTTP method, URI, request body, and other details. This approach provides fine-grained control over requests.

Annotation Parameters

Usage Examples

@Test
void shouldGetBooks(
        @Get("/users/1/books?page=2") Page<Book> books
) {
    // Perform test assertions using the retrieved books
    // ...
}

@Test
void shouldGetNotFound(
        @Get(value = "/users/1/books?page=2", expectedStatus = HttpStatus.NOT_FOUND) ErrorDto errorDto
) {
    // ...
}

@Test
void shouldCreateBook(
        @Post(value = "/books", expectedStatus = HttpStatus.CREATED) Request<Book> request
) {
    // Create a book instance
    Book book = ...

    // Perform the request and retrieve the response
    Response<Book> response = request.body(book).perform();
    Book createdBook = response.getBody();
    // Perform test assertions using the created book
    // ...
}

@Test
void shouldUpdateBook(
        @Put(value = "/books", body =  @Content(file = "/book.json")) Book updatedBook
) {
    // Perform test assertions using the updated book
    // ...
}

@Test
void shouldDeleteBook(
        @Delete(value = "/books/{id}", expectedStatus = HttpStatus.NO_CONTENT) Response<Void> response
) {
    // Perform test assertions for successful deletion
    // ...
}

Type Options

Available in both the API client interfaces and when declaring requests as test parameters

Developers have flexibility in choosing how they handle response and request types. Result Type Options offer a convenient way to interact with API responses for diverse testing scenarios.

1. Object Result Type (Page<Book>, Book)

Developers can directly retrieve the response body as an object, simplifying test assertions.

Interface Usage:
@GetMapping("/{id}")
UserDto findById(@PathVariable int id);
Test Parameter Usage:
@Get("/users/1/books?page=2") Page<Book> books

2. Response Object (Response<Book>, Response<Void>)

Developers can declare the response type as an object to access detailed information such as status and headers.

Interface Usage:
@GetMapping("/{id}")
Response<UserDto> findById(@PathVariable int id);
Test Parameter Usage:
@Get("/users/1/books?page=2") Response<Page<Book>> booksResponse

3. Request Object (Request<Book>)

Developers can use the Request type to perform additional customizations before executing the request.

Interface Usage:
@GetMapping("/{id}")
Request<UserDto> findById(@PathVariable int id);
Test Parameter Usage:
@Get("/users/1/books?page=2") Request<Page<Book>> booksRequest

Last updated