Jersey 测试在使用 UriInfo 时给出 NullPointerException

Jersey test gives NullPointerException when using UriInfo

我正在创建一个应该能够使用 REST 创建帐户的应用程序 api。当我写 AccountController.java class 时一切正常。我用邮递员来验证我得到了正确的回复。

所以我的 AccountController.java 工作正常,但我用它编写的单元测试不起作用。当执行单元测试时,它 return 是一个 NullPointerException,这会导致 REST API 中的 InternalServerError。在调试时我发现如果我在 AccountController.java 和 return Response.ok() 中删除 UriInfo 的使用而不是创建测试成功。

所以我的问题是。我如何正确 test/mock 一个 returns 和 URI 的方法?

以下是所有相关的 classes 和依赖项。 Account.java class 在另一个包中。但是主应用程序和包含 Account.java 的项目都是同一个父 pom 的一部分。我不确定这是否与我的问题相关。

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
}

测试依赖项

<!-- 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>

所以我终于想通了。 AccountController.java 这一行的某处抛出了 NullPointerException

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

这只发生在使用我的 JerseyUnitTest 时,所以我猜 Jersey 必须改变 UriInfo.

的某些行为

最终我通过覆盖 Account.java 中的 equals 解决了问题。