Skip to content

Commit

Permalink
Added withFileUpload method to the JUnit DSL to support multipart fil…
Browse files Browse the repository at this point in the history
…e uploads #462
  • Loading branch information
Ronald Holshausen committed Dec 6, 2017
1 parent 2aee521 commit 3f9a03e
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 0 deletions.
@@ -0,0 +1,53 @@
package au.com.dius.pact.consumer.junit

import au.com.dius.pact.consumer.Pact
import au.com.dius.pact.consumer.PactProviderRuleMk2
import au.com.dius.pact.consumer.PactVerification
import au.com.dius.pact.consumer.dsl.PactDslWithProvider
import au.com.dius.pact.model.RequestResponsePact
import org.apache.http.client.methods.RequestBuilder
import org.apache.http.entity.ContentType
import org.apache.http.entity.mime.HttpMultipartMode
import org.apache.http.entity.mime.MultipartEntityBuilder
import org.apache.http.impl.client.CloseableHttpClient
import org.apache.http.impl.client.HttpClients
import org.junit.Rule
import org.junit.Test

class ExampleFileUploadSpec {

@Rule
@SuppressWarnings('PublicInstanceField')
public final PactProviderRuleMk2 mockProvider = new PactProviderRuleMk2('File Service', this)

@Pact(provider = 'File Service', consumer= 'Junit Consumer')
RequestResponsePact createPact(PactDslWithProvider builder) {
builder
.uponReceiving('a multipart file POST')
.path('/upload')
.method('POST')
.withFileUpload('file', 'data.csv', 'text/csv', '1,2,3,4\n5,6,7,8'.bytes)
.willRespondWith()
.status(201)
.body('file uploaded ok')
.toPact()
}

@Test
@PactVerification
void runTest() {
CloseableHttpClient httpclient = HttpClients.createDefault()
httpclient.withCloseable {
def data = MultipartEntityBuilder.create()
.setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
.addBinaryBody('file', '1,2,3,4\n5,6,7,8'.bytes, ContentType.create('text/csv'), 'data.csv')
.build()
def request = RequestBuilder
.post(mockProvider.url + '/upload')
.setEntity(data)
.build()
println('Executing request ' + request.requestLine)
httpclient.execute(request)
}
}
}
Expand Up @@ -11,11 +11,17 @@
import au.com.dius.pact.model.matchingrules.MatchingRulesImpl;
import au.com.dius.pact.model.matchingrules.RegexMatcher;
import com.mifmif.common.regex.Generex;
import org.apache.http.HttpEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.json.JSONObject;
import org.w3c.dom.Document;

import javax.xml.transform.TransformerException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
Expand All @@ -25,6 +31,7 @@

public class PactDslRequestWithPath {
private static final String CONTENT_TYPE = "Content-Type";
public static final String MULTIPART_HEADER_REGEX = "multipart/form-data;\\s*boundary=.*";
private final ConsumerPactBuilder consumerPactBuilder;

Consumer consumer;
Expand Down Expand Up @@ -376,4 +383,28 @@ public PactDslRequestWithPath matchQuery(String parameter, String regex, List<St
query.put(parameter, example);
return this;
}

/**
* Sets up a file upload request. This will add the correct content type header to the request
* @param partName This is the name of the part in the multipart body.
* @param fileName This is the name of the file that was uploaded
* @param fileContentType This is the content type of the uploaded file
* @param data This is the actual file contents
*/
public PactDslRequestWithPath withFileUpload(String partName, String fileName, String fileContentType, byte[] data)
throws IOException {
HttpEntity multipart = MultipartEntityBuilder.create()
.setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
.addBinaryBody(partName, data, ContentType.create(fileContentType), fileName)
.build();
OutputStream os = new ByteArrayOutputStream();
multipart.writeTo(os);

requestBody = OptionalBody.body(os.toString());
requestMatchers.addCategory("header").addRule(CONTENT_TYPE, new RegexMatcher(MULTIPART_HEADER_REGEX,
multipart.getContentType().getValue()));
requestHeaders.put(CONTENT_TYPE, multipart.getContentType().getValue());

return this;
}
}
Expand Up @@ -9,11 +9,17 @@
import au.com.dius.pact.model.PactReader;
import com.mifmif.common.regex.Generex;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.http.HttpEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.json.JSONObject;
import org.w3c.dom.Document;

import javax.xml.transform.TransformerException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
Expand All @@ -26,6 +32,7 @@

public class PactDslRequestWithoutPath {
private static final String CONTENT_TYPE = "Content-Type";
public static final String MULTIPART_HEADER_REGEX = "multipart/form-data;\\s*boundary=.*";
private final ConsumerPactBuilder consumerPactBuilder;
private PactDslWithState pactDslWithState;
private String description;
Expand Down Expand Up @@ -270,4 +277,28 @@ public PactDslRequestWithPath matchPath(String pathRegex, String path) {
return new PactDslRequestWithPath(consumerPactBuilder, consumerName, providerName, pactDslWithState.state, description, path,
requestMethod, requestHeaders, query, requestBody, requestMatchers, requestGenerators);
}

/**
* Sets up a file upload request. This will add the correct content type header to the request
* @param partName This is the name of the part in the multipart body.
* @param fileName This is the name of the file that was uploaded
* @param fileContentType This is the content type of the uploaded file
* @param data This is the actual file contents
*/
public PactDslRequestWithoutPath withFileUpload(String partName, String fileName, String fileContentType, byte[] data)
throws IOException {
HttpEntity multipart = MultipartEntityBuilder.create()
.setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
.addBinaryBody(partName, data, ContentType.create(fileContentType), fileName)
.build();
OutputStream os = new ByteArrayOutputStream();
multipart.writeTo(os);

requestBody = OptionalBody.body(os.toString());
requestMatchers.addCategory("header").addRule(CONTENT_TYPE, new RegexMatcher(MULTIPART_HEADER_REGEX,
multipart.getContentType().getValue()));
requestHeaders.put(CONTENT_TYPE, multipart.getContentType().getValue());

return this;
}
}

0 comments on commit 3f9a03e

Please sign in to comment.