← Java

Java · 15 / 18

JUnit, semantic PDF tests and Testcontainers

Verify the contents of a real PDF and choose tests according to the guarantee being demonstrated.

  • Medium
  • Intermediate
  • 45 min

Prerequisites: Understand PostgreSQL, JPA and Flyway

A test must check an observable guarantee. For a PDF, that may be page count, field value or archive contents. Comparing every byte can fail because of metadata while saying little about domain contents. This tutorial adds a semantic test to the generator from tutorial 11, then distinguishes unit, integration and database contract tests.

01Extend the test setup

Use Main.java from tutorial 11. The new pom.xml adds JUnit. Save the test at src/test/java/tutorial/PdfTest.java. Maven Surefire discovers the test class and runs it during test.

pom.xml · xmlOpen file
<project xmlns="http://maven.apache.org/POM/4.0.0">
  <modelVersion>4.0.0</modelVersion>
  <groupId>example</groupId><artifactId>learning</artifactId><version>1.0</version>
  <properties><maven.compiler.release>21</maven.compiler.release><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties>
  <dependencies><dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>3.0.8</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-csv</artifactId><version>1.14.1</version></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter</artifactId><version>5.13.4</version><scope>test</scope></dependency></dependencies>
  <build><plugins>
    <plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.14.1</version></plugin>
    <plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><version>3.5.3</version></plugin>
  </plugins></build>
</project>

Run / check

mvn package dependency:copy-dependencies
java -cp "target/classes:target/dependency/*" tutorial.Main

02Read an actually generated PDF

The test calls the generator and loads result.pdf using PDFBox. It checks page count and the named field’s value. finally removes only the file produced by the learning program. Use a separate learning directory.

src/test/java/tutorial/PdfTest.java · javaOpen file
package tutorial;
import java.nio.file.Files;
import java.nio.file.Path;
import org.apache.pdfbox.Loader;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class PdfTest {
  @Test void recipientIsPreservedInGeneratedPdf() throws Exception {
    try {
      Main.main(new String[0]);
      try (var document = Loader.loadPDF(Path.of("result.pdf").toFile())) {
        assertEquals(1, document.getNumberOfPages());
        assertEquals("Ada", document.getDocumentCatalog().getAcroForm()
          .getField("recipient").getValueAsString());
      }
    } finally { Files.deleteIfExists(Path.of("result.pdf")); }
  }
}

Run / check

mvn test

03Detect an incorrect change

Change Ada in the generator to Lin. The test must fail on the expected field value. Restore the change. This shows which concrete domain statement the test protects.

04Add suitable kinds of tests

Unit tests check state rules without infrastructure. HTTP tests check the full upload and download workflow. Testcontainers starts a real PostgreSQL instance for adapter contracts. If Docker is missing, such a test must visibly be skipped rather than counted as passed database evidence.

Expected result

mvn test confirms one page and recipient = Ada. The test detects a deliberately changed recipient name.

Your exercise

Also verify the recipient field exists before reading its value.

Show the solution and explanation

Store the field in a variable and use assertNotNull with a clear message. Then assertEquals checks its contents. A missing field and an incorrect value become distinguishable causes.

Project context and sources

The example is simplified for learning. The linked source version shows its use in the project and the checks applied there.