Search code examples
javaunit-testingjunitjerseyjersey-test-framework

JerseyTest framework path encoding replaces ? with %3F


I have a failing test, which should be passing. The service works fine, but the JerseyTest JUnit test is failing with status 400.

Using Postman or a browser, when I try this URL against the deployed service:

http://localhost:8080/myService/123?appId=local&userId=jcn

I get correct result, status 200 and see the following in the log:

    INFO: 4 * Server has received a request on thread http-nio-8080-exec-5
4 > GET http://localhost:8080/myService/123?appId=local&userId=jcn

Note the ? in the URL, which is correct.

But when I try this unit test in my JeryseyTest-extended Junit class:

@Test
public void getWithCorrectUrlExecutesWithoutError()
{
    String x = target("myService/123?appId=local&userId=jcn").request().get(String.class);
}

it fails with a status 400, and I see this in the log:

INFO: 1 * Server has received a request on thread grizzly-http-server-0
1 > GET http://localhost:9998/myService/123%3FappId=local&userId=jcn

Note that the ? has been replaced with %3F.

I don't understand what is happening. If I try the "%3F" URL in the browser, I see the same 400 error from the unit test. So I feel somewhat certain that the encoding of the url is the problem.

Here is my Jersey resource, partial listing because it's kind of long, but I am pretty sure this is the relevant part:

    @Component
    @Path("/myService")
    public class MyResource
    {
        @Autowired
        SomeDao someDao;

        @NotBlank
        @QueryParam("appId")
        private String appId;

        @NotBlank
        @QueryParam("userId")
        private String userId;


        @GET
        @Path("/{id}")
        @Produces(MediaType.APPLICATION_JSON)
        public Status getStatus(@NotBlank @PathParam("id") String id)
        {
            errors = new ArrayList<>();
            Status retVal;

            if(validateId(id))
            {
                retVal = someDao.getStatus(id);
            }
            else
            {
                throw new BadParameterException(String.join(" | ", errors));
            }

            return retVal;
        }
}

Solution

  • You can use the queryParam method on your WebTarget instance:

    String x = target("myService/123")
        .queryParam("appId", "local")
        .queryParam("userId", "jcn")
        .request()
        .get(String.class);