Site icon Experiences Unlimited

Testing the File Upload API in Spring Boot

In one of my previous post, I had created an API to upload file. In this post I will write a JUnit test to test the API. We will test the complete flow right from uploading till it is copied to the file system and then we will also see how to mock the FileService class so that the uploaded file is not copied to the file system.

File Upload REST API

@Slf4j
@RestController
@RequestMapping("/api/files")
public class FileUploadAPIController {

  @Autowired FileService fileService;

  @PostMapping("/upload")
  public ResponseEntity<?> handleFileUpload(
    @RequestParam("uploaded-file") List<MultipartFile> uploadedFiles
  ) throws IOException {
    log.debug("Uploaded files size : {}", uploadedFiles.size());
    fileService.copyFile(uploadedFiles);
    return ResponseEntity.ok().build();
  }
}

Testing the API without mocking FileService

The below code is for testing the file upload API. In this we are going to test the complete flow where a file is sent to the API and then copid to the file system:

@SpringBootTest
@AutoConfigureMockMvc
public class FileUploadAPIControllerE2ETest {
  @Autowired
  MockMvc mockMvc;

  @Value("${app.document-root}")String documentRoot;

  List<Path> filesToBeDeleted = new ArrayList<>();

  @Test
  public void test_handleFileUpload() throws Exception {
    String fileName = "sampleFile.txt";
    MockMultipartFile sampleFile = new MockMultipartFile(
      "uploaded-file",
      fileName, 
      "text/plain",
      "This is the file content".getBytes()
    );

    MockMultipartHttpServletRequestBuilder multipartRequest =
      MockMvcRequestBuilders.multipart("/api/files/upload");

    mockMvc.perform(multipartRequest.file(sampleFile))
      .andExpect(status().isOk());

    Path docRootPath = Path.of(documentRoot, fileName);
    filesToBeDeleted.add(docRootPath);
    assertThat(Files.exists(docRootPath)).isTrue();

  }

  @AfterEach
  public void cleanup() {
    filesToBeDeleted.forEach(path -> {
      try {
        Files.deleteIfExists(path);
      } catch (IOException e) {
        e.printStackTrace();
      }
    });
  }
}

Testing the API with mock FileService

In this testing we will mock the FileService bean, using @MockBean, which is the bean responsible for copying the uploaded file to the required location in the file system. In this test we will just test the API code without concenring the downstream services it depends on.

@SpringBootTest
@AutoConfigureMockMvc
public class FileUploadAPIControllerTest {
  @MockBean  private FileService fileService;

  @Autowired MockMvc mockMvc;

  @Value("${app.document-root}")String documentRoot;

  @Test
  public void test_handleFileUpload() throws Exception{

    String fileName = "sample-file-mock.txt";
    MockMultipartFile sampleFile = new MockMultipartFile(
        "uploaded-file",
        fileName,
        "text/plain",
        "This is the file content".getBytes());

    MockMultipartHttpServletRequestBuilder multipartRequest =
        MockMvcRequestBuilders.multipart("/api/files/upload");

    mockMvc.perform(multipartRequest.file(sampleFile))
        .andExpect(status().isOk());
  }

  @Test
  public void test_handleFileUpload_NoFileProvided() throws Exception{
    MockMultipartHttpServletRequestBuilder multipartRequest =
        MockMvcRequestBuilders.multipart("/api/files/upload");

    mockMvc.perform(multipartRequest)
        .andExpect(status().isBadRequest());
  }

}

Rest of the code is similar to the one in end to end test previously shown. In this test we dont validate the existence of the file on the file system because the implementation of copying to file system has been mocked and there is no real implementation in the mocked managed bean.

The complete code – API, View and Tests can be found in the Github repo here.

Exit mobile version