Reputation: 1179
I know this question must have been asked a thousand times before, but none of the answers at Stackoverflow work for me. I am trying to create a unit test for a restful api which uses basic authentication. Here is the code for API:
@GET
@Timed
@Path("/getAuthPerson/{id}")
@Produces(MediaType.APPLICATION_JSON)
public Person getAuthPerson(@PathParam("id")int id, @Auth Person user) {
/* use HTTP header:
Authorization : Basic dGVzdDpzZWNyZXQ=
For negative test case, use
Authorization : Basic dGVzdDoxMjM=
*/
if(user.getName().isEmpty()) {
return null;
}
Person p = new Person();
p.setName("Test");
p.setId(0);
p.setAge(10);
return p;
}
This API works when I call RESTful client of browser, my IDE or from Fiddler i.e. I am correctly getting 401 when I don't provide auth header/incorrect header and am able to get back the resource when I provide correct header. However, the unit test api refuses to work, here is the code for unit-test:
public class PersonResourceTest {
private static final PersonDao personDao = mock(PersonDao.class);
@ClassRule
public static final ResourceTestRule resources = ResourceTestRule.builder()
.addResource(new PersonResource(personDao))
.build();
private static Person getDummyPerson() {
Person person = new Person();
person.setName("John Doe");
person.setBirthDateTime(new DateTime("2012-11-21T13:01:33.568Z"));
person.setAge(10);
return person;
}
private final Person person = getDummyPerson();
@Before
public void setup() {
when(personDao.getPerson(eq(123))).thenReturn(person);
// we have to reset the mock after each test because of the
// @ClassRule, or use a @Rule as mentioned below.
reset(personDao);
}
@Test
public void authenticatedTestGetPositive() {
PersonDao testDao = mock(PersonDaoMongoImpl.class);
testDao.createPerson(person);
WebResource.Builder builder = resources.client().resource("/persons/getAuthPerson/123").getRequestBuilder();
builder.header("Authorization", "Basic dGVzdDpzZWNyZXQ=");
//builder.header("Authorization", "Basic dGVzdDoxMjM=");
builder.accept(MediaType.APPLICATION_JSON);
Person p = builder.get(Person.class);
assertThat(p).isEqualTo(person);
verify(testDao).getPerson(123);
}
}
The unit test which does not involve authentication works perfectly, however this authentication unit test gives this error:
ERROR [2014-08-10 14:48:58,108] com.sun.jersey.spi.container.ContainerRequest: A message body reader for Java class com.rms.pilotapi.core.Person, and Java type class com.rms.pilotapi.core.Person, and MIME media type application/octet-stream was not found.
The registered message body readers compatible with the MIME media type are:
*/* ->
com.sun.jersey.core.impl.provider.entity.FormProvider
com.sun.jersey.core.impl.provider.entity.StringProvider
com.sun.jersey.core.impl.provider.entity.ByteArrayProvider
--snipped---
Upvotes: 1
Views: 807
Reputation: 197
You need to register your PersonAuthenticator
(or whichever name you used for your Authenticator) in the JUnit testrule (@ClassRule
).
The problem is that Jersey tries to deserialize your parameter @Auth Person user
, which should be handled by your authenticator.
Upvotes: 2