skip to content

In REST Assured, how do given().body()'s String, byte[], File and InputStream overloads differ?

level: middleimportance: must knowfreq 55%

answer

  1. no object mapper touches these four
  2. which default content type is derived
  3. bytes and streams mean octet-stream
  4. a File under text/plain is read as text

basics

~20 s

All four store the argument verbatim as the request body; no object mapper runs. They differ in the Content-Type REST Assured picks when none is set. A byte array or stream gives application/octet-stream, a String or File text/plain.

solid answer

~40 s

`RequestSpecification` declares seven `body` overloads, and these four are the **raw** ones: each null-checks its argument and stores it as the request body, full stop. No mapper is consulted — that is `body(Object)`'s job, a different subject. Passing `null` to any of them throws `IllegalArgumentException: body cannot be null`. What separates them is the Content-Type REST Assured derives when you set none: `byte[]` and `InputStream` produce `application/octet-stream`, while `String` **and `File`** fall through to `text/plain`, both with `EncoderConfig`'s default content charset appended as `; charset=ISO-8859-1`. That `File` fallback is the trap — under a text content type the file is read into a `String` before it is sent, which mangles a photo or a zip. Set `contentType(ContentType.BINARY)`, or the real media type, whenever the body is a `File` or an `InputStream`.

code

java · 14 lines
java
import java.io.File;
import io.restassured.http.ContentType;

import static io.restassured.RestAssured.given;

// Without the contentType() call this would go out as
// text/plain; charset=ISO-8859-1, and the JPEG would be read as text
given()
    .contentType(ContentType.BINARY)
    .body(new File("scale-2026-09-07.jpg"))
.when()
    .put("/hawks/HW-118/weigh-ins/WI-9032/scale-photo")
.then()
    .statusCode(204);

go deeper

for a junior

Know that body() takes a ready-made payload and that you normally pair it with contentType(). Being able to send a JSON string and assert the status back is enough at this level.

for a middle

Explain the derived content types for each of the four argument shapes, and why nothing is serialized on this path. That mechanics layer is exactly what this tier is asked about.

for a senior

Be ready to diagnose a corrupted upload back to a File body with no content type set, and to say why the failure shows up as bad bytes rather than as an exception.

for a principal

Decide whether your suite lets raw bodies be written ad hoc or funnels them through helpers that always set a media type, and defend that against the readability cost of an extra layer.

## The four raw overloads `RequestSpecification` declares seven `body` overloads. Four are *raw* — `body(String)`, `body(byte[])`, `body(File)` and `body(InputStream)` — and each one does exactly two things: reject a `null` argument, then assign it to the specification's request body. Nothing is parsed, nothing is converted, and no `ObjectMapper` is consulted. The remaining three take an `Object` and hand it to a mapper, which is a separate topic with its own rules. The null check is literal and shared: all four route through the same helper, so `given().body((File) null)` throws `IllegalArgumentException` with the message `body cannot be null` rather than quietly sending nothing. Because these are ordinary Java overloads, **the static type of the expression picks the method at compile time**. Assigning a JSON string to an `Object` variable first and then calling `body(thatVariable)` binds to `body(Object)` and runs a mapper over it, which is a different code path from the one you thought you were on. ## What Content-Type each one produces When the request carries no explicit content type, REST Assured derives one from the shape of the body. For a falconry weight-log API this is what a `PUT` of a raw payload sends: | body argument | derived Content-Type when you set none | | --- | --- | | `body(weighInJson)` (a `String`) | `text/plain; charset=ISO-8859-1` | | `body(new File("scale-2026-09-07.jpg"))` | `text/plain; charset=ISO-8859-1` | | `body(photoBytes)` | `application/octet-stream; charset=ISO-8859-1` | | `body(new FileInputStream(photo))` | `application/octet-stream; charset=ISO-8859-1` | Three points follow from that table: - `byte[]` and `InputStream` are the only two shapes REST Assured recognises as binary. A `File` is not one of them, so it falls through to the text branch. - The `; charset=` suffix is `EncoderConfig`'s default content charset, which is `ISO-8859-1`. It is appended even to `application/octet-stream`, which surprises most people the first time they read a request log. - A JSON body sent as `body(jsonString)` with no `contentType(ContentType.JSON)` goes out as `text/plain`, and most services answer that with a 415 rather than parsing it. ## Why the `File` default is a real trap The derived content type does not just decorate the request — it selects the encoder. Under a binary content type the payload is streamed: a `File` is opened as a `FileInputStream` and wrapped with its known length, and an `InputStream` is passed through as it is. Under a *text* content type the encoder takes a different branch and **reads the whole `File` into a `String`** using the charset from the content type, then sends that string. For a CSV of hawk weights that is harmless. For a scale photograph it is not: the bytes are decoded as ISO-8859-1 text and re-encoded, and the server receives a corrupted image with no error anywhere in the chain. The fix is one call: ```java given().contentType(ContentType.BINARY) // or "image/jpeg" .body(new File("scale-2026-09-07.jpg")) .when().put("/hawks/HW-118/weigh-ins/WI-9032/scale-photo") .then().statusCode(204); ``` Set the real media type whenever the body is a `File` or an `InputStream` and you never meet this. ## Body versus form parameters, and body versus parts Two combinations behave in ways worth knowing before you hit them: 1. **Form parameters and a body together** on a body-bearing method raise `IllegalStateException` with the message `You can either send form parameters OR body content in POST, not both!`. The check runs before anything is sent, so the failure is immediate and readable. 2. **A body and `multiPart(...)` together** fail silently instead. Once the part list is non-empty the assembled body content becomes an empty byte array, and the multipart encoder rebuilds the payload from the parts alone — your `body(...)` argument never leaves the process. The asymmetry is worth remembering: one conflict shouts, the other does not. ## A checklist for choosing an overload - Sending JSON or XML you already have as text? `body(String)` plus an explicit `contentType(...)`. - Sending bytes you built in the test? `body(byte[])` — the type is already right. - Sending a fixture from disk? `body(File)` **plus** `contentType(...)`, always. - Streaming something large or generated? `body(InputStream)`, remembering the stream is consumed once and cannot be replayed by a retry you write around the call. - Sending a domain object? That is `body(Object)`, a different overload family with mapper rules of its own. The rule that ties them together is short: the raw overloads never transform your argument, but the content type you do or do not set decides how it reaches the wire.

  • What does REST Assured do when a POST sets both formParam(...) and body(...)?
    It throws `IllegalStateException` with the message `You can either send form parameters OR body content in POST, not both!`, and it throws before anything is sent. The two are mutually exclusive because a url-encoded form payload and a raw body would both claim the same request body. Pick one, or move the values into multipart parts if the endpoint accepts them.
  • Why can given().body(someObject) behave differently from given().body(someString)?
    Java resolves the overload from the static type at compile time. A `String` binds to the raw `body(String)` overload and is stored verbatim; anything typed as `Object` binds to `body(Object)`, which hands the value to an object mapper chosen from the request's content type. Widening a `String` to `Object` therefore changes the code path, and the mapper rules are a separate subject.

saying these in an interview costs you the question

  • Thinks body(byte[]) serializes through Jackson like body(Object)
  • Assumes a File body is always streamed as binary
  • Says body(null) sends an empty body instead of throwing
  • Believes REST Assured infers a content type from the file extension
  • Claims body() and formParam() can both be set on one POST