Invalid Json: No content to map due to end-of-input when using play body parser

The short answer is: on your FakeRequest in your controller test use the withBody method instead of withJsonBody.

I had this issue as well, and I embarrassingly spent hours on it until I figured it out. The long answer is that FakeRequest's withJsonBody returns a FakeRequest[AnyContentAsJson], and since your controller is expecting a JsValue (not an AnyContentAsJson), when you call apply() on your action it fails to match this apply method, which is the one you want:

def apply(request: Request[A]): Future[Result]

and instead hits this apply method:

def apply(rh: RequestHeader): Accumulator[ByteString, Result]

and thus since you're not then passing any Bytes to the Accumulator, you get the unexpected end-of-input error message you're getting.