A home for additional useful unit testing modules for Java.
Java
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
.mvn/wrapper
src
.checkstyle
.gitignore
Jenkinsfile
README.md
license.txt
mvnw
mvnw.cmd
pom.xml

README.md

units4j

A home for additional useful unit testing modules for Java.

Build Status Coverage Status Maven Central Javadocs LGPLv3 License Java Development Kit 1.8


Features


Asserting test coverage

A good approach is to have at least one test class for every production class.

If you have classes this rule-of-thumb does not apply, you can:

  • Write a dummy test class with a comment that describes why not...
  • Use an AssertCoverage.ClassFilter to exclude the classes
@Test
public void testCoverage() {
    AssertCoverage.assertEveryClassHasATest(new File("src/main/java"));
}

Asserting package dependencies

It's a good practice enforcing package dependencies to avoid high coupling and package cycles.

You simply define a dependency description in your "src/test/resources" folder. For an example see units4j.xml).

@Test
public void testAssertDependencies() {
    AssertDependencies.assertRules(getClass(), "/units4j.xml", new File("target/classes"));
}

Asserting methods are not used

Example: Prevent a java.lang.ArithmeticException Non-terminating decimal expansion; no exact representable decimal result." caused by calling BigDecimal's divide or setScale without a rounding mode:

// Path to '*.class' files
File classesDir = new File("target/classes");

// Can be used to exclude some files/packages
FileFilter fileFilter = new FileFilter() {
    @Override
    public boolean accept(File file) {
        return !file.getPath().contains("my/pkg/to/exclude");
    }
};

// Define methods to find
MCAMethod divide = new MCAMethod("java.math.BigDecimal", "java.math.BigDecimal divide(java.math.BigDecimal)");
MCAMethod setScale = new MCAMethod("java.math.BigDecimal","java.math.BigDecimal setScale(int)");

// Fails if any class calls one of the two methods
AssertUsage.assertMethodsNotUsed(classesDir, fileFilter, divide, setScale);

Assert that JPA entities are valid

Uses JBoss Jandex to validate JPA entity classes.

import static org.fuin.units4j.JandexAssert.assertThat;
// Collect all class files
File dir = new File("target/classes");
List<File> classFiles = Units4JUtils.findAllClasses(dir);
Index index = Units4JUtils.indexAllClasses(classFiles);

// Verify that all classes annotated with @Entity or @MappedSuperclass observe 
// the rules for JPA entities (Class not final + No final methods + ...).
assertThat(index).hasOnlyValidJpaEntities();

Assert that methods have information if null is allowed or not

WORK IN PROGRESS See Issue #9

It's a good style to define a precondition for method arguments and postconditions for return values of externally used methods. Especially the questions "Can I pass null?" or "Does the method return null values?" is a common source of confusion. This assertion makes sure that all return values and parameters of all public, protected and package-private methods have either a @NotNull or a @Nullable annotation.

Example:

public interface MyInterface {
    
    // Post condition says the return value is never null
    @NotNull
    public Boolean myMethodA();
    
    // Pre condition says the first value cannot be null, but it's OK for the second argument
    public void myMethodB(@NotNull Integer abc, @Nullable String def);

    // Post condition says the return value may be null
    @Nullable
    public Long myMethodC();
    
}   

Test:

import static org.fuin.units4j.JandexAssert.assertThat;
// Collect all class files
File dir = new File("target/classes");
List<File> classFiles = Units4JUtils.findAllClasses(dir);
Index index = Units4JUtils.indexAllClasses(classFiles);

// Verify that all methods make a statement if null is allowed or not 
assertThat(index).hasNullabilityInfoOnAllMethods();

Snapshots

Snapshots can be found on the OSS Sonatype Snapshots Repository.

Add the following to your .m2/settings.xml to enable snapshots in your Maven build:

<repository>
    <id>sonatype.oss.snapshots</id>
    <name>Sonatype OSS Snapshot Repository</name>
    <url>http://oss.sonatype.org/content/repositories/snapshots</url>
    <releases>
        <enabled>false</enabled>
    </releases>
    <snapshots>
        <enabled>true</enabled>
    </snapshots>
</repository>