Unit-Testing JAX-RS with Jersey Test Framework and Weld


요 근래 JAX-RS에 기반한 라이브러리를 하나 만들던 중 단위 테스트에 문제가 생겨서 SO에 이것 저것 물어봤다.

References

JAX-RS

만들고 있는 라이브러리는 JAX-RS와 DI만 사용한다.

<dependency>
  <groupId>javax.inject</groupId>
  <artifactId>javax.inject</artifactId>
  <scope>provided</scope>
</dependency>
<dependency>
  <groupId>javax.ws.rs</groupId>
  <artifactId>javax.ws.rs-api</artifactId>
  <scope>provided</scope>
</dependency>

Jersey Test Framework

단위 시험을 하기위해 다음과 같이 Jersey Test Framework을 추가하였다.

<dependency>
  <groupId>org.glassfish.jersey.test-framework.providers</groupId>
  <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
  <scope>test</scope>
</dependency>

Weld

Jersey가 사용하고 있는 HK2(JSR-330)은 주입(injection)은 잘 수행하는 듯 하나 JSR-250에 해당하는 @PostConstruct 등은 수행하지 못한다. 다음과 같이 dependency를 추가했다.

<dependency>
  <groupId>org.glassfish.jersey.ext.cdi</groupId>
  <artifactId>jersey-weld2-se</artifactId>
  <scope>test</scope>
</dependency>

그리고 다음과 같이 Weld를 적용시켰다.

@Override
protected Application configure() {

    final Weld weld = new Weld();
    weld.initialize();
    Runtime.getRuntime().addShutdownHook(new Thread(() -> weld.shutdown()));

    // ...
}

Using Maven Embedded GlassFish Plugin 4.x


It seems the way I used to work with embedded-glassfish is changed.

references

maven-embedded-glassfish-plugin

<plugin>
  <groupId>org.glassfish.embedded</groupId>
  <artifactId>maven-embedded-glassfish-plugin</artifactId>
  <version>4.0</version>
  <configuration>
    <port>8080</port>
  </configuration>
  <executions>
    <execution>
      <goals>
        <goal>deploy</goal>
      </goals>
      <phase>none</phase>
      <configuration>
        <app>target/${project.build.finalName}.${project.packaging}</app>
        <contextRoot>/</contextRoot>
      </configuration>
    </execution>
  </executions>
  <dependencies>
    <dependency>
      <groupId>org.glassfish.main.extras</groupId>
      <artifactId>glassfish-embedded-all</artifactId>
      <version>4.1</version>
    </dependency>
  </dependencies>
</plugin>

embedded-glassfish:run

$ mvn embedded-glassfish:run
...
Hit ENTER to redeploy, X to exit
_

Now whenever you build your war, you just hit the Enter to redeploy.

launching 3rd party servlets using jetty for unit testing


References

Apache Maven

<dependency>
  <!-- I'm not sure this is the minimum dependency -->
  <groupId>org.eclipse.jetty</groupId>
  <artifactId>jetty-servlet-tester</artifactId>
  <scope>test</scope>
</dependency>

TestNG


    private static final PORT;

    static {
        PORT = ThreadLocalRandom.current().nextInt(1024, 65536);
    }

    private static Server SERVER;

    @BeforeClass
    public static void startServer() throws Exception {
        SERVER = new Server(PORT);
        final ServletHandler handler = new ServletHandler();
        SERVER.addServeltHandler(handler);
        handler.addServletWithMapping(SomeServlet.class, "/some");
        SERVER.start();
    }

    @AfterClass
    public static void stopServer() throws Exception {
        SERVER.stop();
        SERVER = null;
    }

    @Test
    public void test() throws MalformedURLException {
        final URL url = new URL("http://localhost:" + PORT + "/some");
    }

completePendingCommand of Commons-Net


When I tried like this,

try(OutputStream fileStream = ftpClient.storeFileStream(remote)) {
    // do some
    final boolean commandCompleted
        = ftpClient.completePendingCommand();
    // check the result
}

I found that completePendingCommand() hangs.
The method apparently have to be invoked after the stream is closed.

try(OutputStream fileStream = ftpClient.storeFileStream(remote)) {
    // do some
}
final boolean commandCompleted
    = ftpClient.completePendingCommand();
// check the result