Grails: Functional Testing a File Upload using HTTPBuilder / Spock

Let’s continue a bit more on the previous post and see how can we do functional testing of the same file-upload feature using HTTPBuilder and Spock libraries.

It needs to be a functional test and not an integration test, because for Grails integration tests, there is no real HTTP layer that comes in the picture to separate the HTTP client requests from your Grails application on the server. Functional tests allow us to hit the application to do the file upload, as normal users of the application would – going through the various layers of the application, verifying on the way various other things like security, URL mappings, etc, etc. How much more real and useful, the testing can get! ๐Ÿ™‚

Although HTTPBuilder usually makes such testing a piece of cake, when it comes to making multipart/form-data requests, there is no direct support in it I could find. After searching here and there, I found that it is, eventually, fairly easy to plug-in a multipart entity in a HTTPBuilder post request, as shown in the example below.

Note: You need to additionally use the HTTPMime module of Apache HTTPComponents project.

import static groovyx.net.http.Method.POST

import groovyx.net.http.HTTPBuilder

import javax.servlet.http.HttpServletResponse

import org.apache.http.entity.mime.MultipartEntity
import org.apache.http.entity.mime.content.FileBody

import spock.lang.Specification

class FileUploadSpec extends Specification
{
    def baseUrl = 'http://localhost:8080/<yourapp>' // your app URL
    
    def 'upload image'()
    {
        when: 'uploading image'
        def imageType = 'image/jpeg'
        def imgFile = new File('<path to some existing image file>')
        assert imgFile.exists()

        def cbFile = new FileBody(imgFile, imageType)

        def http = new HTTPBuilder(baseUrl)
        
        http.auth.basic '<login id>', '<password>' // login credentials
        
        resp = http.request(POST) { req ->
            uri.path = 'user' // controller that recieves the file upload post request
            
            def mpEntity = new MultipartEntity()
            mpEntity.addPart("profileImg", cbFile)
            
            req.entity = mpEntity
        }
        
        then: 'there was no problem faced'
        resp.status == HttpServletResponse.SC_OK
        ...
        ...
    }
}

That’s it. Simple, isn’t it? ๐Ÿ™‚

Advertisements