It's pretty common case to generate file on the backend and let user to download it. But how to test it? I found testing of this scenario not quite well documented. So here's my bit.
We have to use getAsyncResult
method from MvcResult
interface, which enables us to retrieve content provided using StreamingResponseBody
. So first, let's look how to generate file in the controller.
I am going to use Kotlin btw. 😎
Streaming body with StreamingResponseBody
Let's say we want to enable user to download some fine, which is not very small. For the demo I will just generate a text file containing a lot of a
characters.
@Controller
@RequestMapping(value = ["/api/v1/03/get-file"])
class FileProducingController {
@GetMapping(value = [""], produces = ["application/text"])
fun export(): ResponseEntity<StreamingResponseBody> {
return ResponseEntity
.ok()
// set a filename
.header(
"Content-Disposition",
"""attachment; filename="%file.txt""""
)
.body(
// stream the body
StreamingResponseBody { out: OutputStream ->
val text = "a".repeat(1000000)
out.write(text.toByteArray())
out.close()
}
)
}
}
So what I am doing here is that I am setting the file name, which is the default when user downloads it in a browser. And then I am writing the text to the StreamResponseBody's output.
Finally the testing part
So when I want to test it I have to do this.
@SpringBootTest
@AutoConfigureMockMvc
internal class FileProducingControllerTest {
@field:Autowired
lateinit var mvc: MockMvc
@Test
fun `produces correct body`() {
val result = mvc.perform(
MockMvcRequestBuilders.get("/api/v1/03/get-file")
)
.andDo { it.asyncResult }
.andReturn()
val content = result.response.contentAsString
assertEquals("a".repeat(1000000), content)
}
}
Notice the part with it.asyncResult
. Without this part the test would fail. There will be just part of the output in the response's contentAsString
result, because it won't wait for the stream to end. You can try this by removing the part and see it fails.
Tolgee is an open-source solution for software localization. It saves developer's time. Go to Tolgee.io and have fun!