Maiko Kingma Maiko Kingma - 25 days ago 7
reST (reStructuredText) Question

Jersey test gives NullPointerException when using UriInfo

I am creating a application that should be able to create an account using a REST api. When I wrote the

AccountController.java
class everything worked fine. I used postman to verify that I got the right response.

So my
AccountController.java
works correctly but the unit test I wrote with it don't work. When the unit test is executed it returns a
NullPointerException
which results in a InternalServerError within the REST API. While debugging i found out that if I remove the use of UriInfo in
AccountController.java
and return Response.ok() instead of created the test is successfull.

So my question is. How do i properly test/mock a method that returns and URI?

Bellow are all relevant classes and dependencies. The
Account.java
class is in another package. But both the main application as the project that contains
Account.java
are part of the same parent pom. I am not sure if this is relevant to my question.

AccountController.java



@Stateless
@Path("/accounts")
public class AccountController {

@Inject
private AccountService accountService;

@Context
private UriInfo uriInfo;

@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response create(Account account) {
final Account newAccount = accountService.create(account);
System.out.println("Pre uriinfo message");
//Removing this line and returning Response.ok() removes the exception
final URI uri = uriInfo.getAbsolutePathBuilder().path(newAccount.getId() + "").build();
System.out.println("Post uriinfo message");
return Response.created(uri).entity(newAccount).build();
}
}


AccountControllerTest.java



@RunWith(MockitoJUnitRunner.class)
public class AccountControllerTest extends JerseyTest {

@Mock
private AccountService service;

@Override
protected Application configure() {
final ResourceConfig config = new ResourceConfig(AccountController.class);
config.register(new AbstractBinder() {
@Override
protected void configure() {
bind(service).to(AccountService.class);
}
});
return config;
}

@Test
public void createUserTest() throws Exception {
final Account testAccount = new Account("testName", "test@mail.nl");
when(service.create(testAccount))
.thenReturn(testAccount);

System.out.println("Create account test");
//Create a new Account
final Response correctResult = target("/accounts")
.request(MediaType.APPLICATION_JSON)
.post(Entity.json(testAccount));
Assert.assertEquals(HTTP_CREATED, correctResult.getStatus());
Assert.assertEquals(testAccount, correctResult.readEntity(Account.class));
}
}


Account.java



@Entity
@XmlRootElement
public class Account {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(nullable = false)
private String fullName;
@Column(unique = true, nullable = false)
private String mail;
private boolean active;

public Account() { }

public Account(String fullName, String mail) {
this.fullName = fullName;
this.mail = mail;
}

//Contains getters&setters
}


Test dependencies



<!-- jersey version for "Jersey Media Json Jackson" & "Jersey Test Framework Provider Jetty" -->
<properties>
<jersey.version>2.26-b03</jersey.version>
</properties>

<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>

<!-- https://mvnrepository.com/artifact/org.mockito/mockito-core -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.9.0</version>
<scope>test</scope>
</dependency>

<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.test-framework.providers/jersey-test-framework-provider-jetty -->
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-jetty</artifactId>
<version>${jersey.version}</version>
<scope>test</scope>
</dependency>

<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.media/jersey-media-json-jackson -->
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey.version}</version>
<scope>test</scope>
</dependency>

<!-- https://mvnrepository.com/artifact/org.jboss.resteasy/resteasy-jaxrs -->
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>3.1.4.Final</version>
<scope>test</scope>
</dependency>

Answer Source

So I finally figured it out. Somewhere on this line in AccountController.java a NullPointerException was thrown:

final URI uri = uriInfo.getAbsolutePathBuilder().path(newAccount.getId() + "").build();

This only happened when using my JerseyUnitTest so i guess Jersey must change some behavior of UriInfo.

Eventually I solved the problem by overriding equals in Account.java.