When using VCR to test a HTTP multipart request, you might experience mismatching cassettes because of multipart boundaries. Multipart boundaries are most often randomly generated by the HTTP library or browser, so when VCR tries to match a multipart request with a cassette, the boundaries will be different and the match will fail.
However, it is quite simple to replace the random boundaries by fixed ones before matching requests. A multipart request will have a Content-Type
header, which not only makes the request recognizable as multipart request but also specifies the exact boundary that is used. In this case I took a cassette from a Ruby project, so the Content-Type
looks like this:
multipart/form-data; boundary=----RubyFormBoundaryTsqIBL0iujC5POpr
Given this header we should be able to simply replace the boundaries with a fixed value. VCR has a configuration option called match_request_on
, which is an array that accepts symbols for predefined request matchers (see https://relishapp.com/vcr/vcr/v/5-0-0/docs/request-matching) or a callable (Proc, Lambda). I'm not a real fan of using procs for this but as long as we create an object that responds to call
we will be fine:
class VCRMultipartBodyMatcher
MULTIPART_HEADER_MATCHER = %r{^multipart/form-data; boundary=(.+)$}
def call(request_1, request_2)
normalized_multipart_body(request_1) == normalized_multipart_body(request_2)
end
private
def normalized_multipart_body(request)
content_type = (request.headers['Content-Type'] || []).first.to_s
return request.body unless multipart_request?(content_type)
boundary = MULTIPART_HEADER_MATCHER.match(content_type)[1]
request.body.gsub(boundary, '----RubyFormBoundaryTsqIBL0iujC5POpr')
end
def multipart_request?(content_type)
return false if content_type.empty?
MULTIPART_HEADER_MATCHER.match?(content_type)
end
end
Now we can tell VCR to use our custom matcher:
VCR.configure do |config|
config.default_cassette_options = {
match_requests_on: [:method, :uri, VCRMultipartBodyMatcher.new]
}
end
Now, when running the test the boundaries of the request and the cassette will be equal, so the cassette will only mismatch if the request parameters differ. 👍
Do you need help with testing your application? At Kabisa we know a lot about writing good tests. Leave us a message if you would like to get in touch.
Top comments (0)