name.didier.david.test4j.assertions.CodingStandardClassAssert Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ndd-test4j Show documentation
Show all versions of ndd-test4j Show documentation
Test4J provides testing support.
The newest version!
package name.didier.david.test4j.assertions;
import static java.lang.reflect.Modifier.isPrivate;
import static java.lang.reflect.Modifier.isProtected;
import static java.lang.reflect.Modifier.isPublic;
import static java.lang.reflect.Modifier.isStatic;
import static com.google.common.base.Throwables.throwIfUnchecked;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import org.assertj.core.api.AbstractClassAssert;
/**
* {@link Class} assertions enforcing coding standard, using AssertJ.
*
* @author ddidier
*/
public class CodingStandardClassAssert
extends AbstractClassAssert {
/**
* Creates a new assertion for the given class.
*
* @param actual the class under test.
*/
protected CodingStandardClassAssert(final Class> actual) {
super(actual, CodingStandardClassAssert.class);
}
/**
* Verifies that the actual {@code Class} is a well formed abstract class. This method checks that the class is not
* final, has no public constructor and at least one protected constructor.
*
* @return this assertion object.
* @throws AssertionError if {@code actual} is {@code null}.
* @throws AssertionError if the actual {@code Class} is final.
* @throws AssertionError if the actual {@code Class} has a public constructor.
* @throws AssertionError if the actual {@code Class} has not a protected constructor.
*/
public CodingStandardClassAssert isAbstract() {
isNotNull();
isNotFinal();
checkHasNoPublicConstructor();
checkHasProtectedConstructor();
return this;
}
/**
* Verifies that the actual {@code Class} is a well formed utility class. This method checks that the class is
* final, has a single private constructor and has only static methods. From
* http://stackoverflow.com/questions/4520216/how-to-add-test-coverage-to-a-private-constructor.
*
* @return this assertion object.
* @throws AssertionError if {@code actual} is {@code null}.
* @throws AssertionError if the actual {@code Class} is not final.
* @throws AssertionError if the actual {@code Class} has more than a single constructor.
* @throws AssertionError if the actual {@code Class} has not a private constructor.
* @throws AssertionError if the actual {@code Class} has not only static methods.
*/
public CodingStandardClassAssert isUtility() {
isNotNull();
isFinal();
try {
checkHasSingleConstructor();
checkIsPrivate(actual.getDeclaredConstructor());
checkInstanciation(actual.getDeclaredConstructor());
checkHasOnlyStaticMethods();
} catch (Exception e) {
// OK to catch Exception here
throwIfUnchecked(e);
throw new RuntimeException(e);
}
return this;
}
// -----------------------------------------------------------------------------------------------------------------
/**
* Asserts that the actual class has a single constructor.
*
* @throws AssertionError if {@code actual} has more than one constructor.
*/
private void checkHasSingleConstructor() {
int constructorCount = actual.getDeclaredConstructors().length;
if (constructorCount > 1) {
failWithMessage("Expected %s to have only one constructor but had %s", actual, constructorCount);
}
}
/**
* Asserts that the given constructor is private.
*
* @param constructor the constructor under test.
* @throws AssertionError if the given constructor is not private.
*/
private void checkIsPrivate(final Constructor> constructor) {
if (constructor.isAccessible() || !isPrivate(constructor.getModifiers())) {
failWithMessage("Expected %s to have a single private constructor", actual);
}
}
/**
* Asserts that the given constructor can be used.
*
* @param constructor the constructor under test.
* @throws AssertionError if the given constructor cannot be used.
*/
private void checkInstanciation(final Constructor> constructor) {
try {
constructor.setAccessible(true);
constructor.newInstance();
} catch (Exception e) {
// OK to catch Exception here
String exceptionName = e.getClass().getName();
failWithMessage("Expected %s to have a usable constructor but it raised %s", actual, exceptionName);
} finally {
constructor.setAccessible(false);
}
}
/**
* Asserts that the actual class has only static methods.
*
* @throws AssertionError if the actual class has an instance method.
*/
private void checkHasOnlyStaticMethods() {
for (Method method : actual.getMethods()) {
if (!isStatic(method.getModifiers()) && method.getDeclaringClass().equals(actual)) {
failWithMessage("Expected %s to have only static methods but has '%s'", actual, method.getName());
}
}
}
/**
* Asserts that the actual class has a protected constructor.
*
* @throws AssertionError if {@code actual} has no protected constructor.
*/
private void checkHasProtectedConstructor() {
for (Constructor> constructor : actual.getDeclaredConstructors()) {
if (isProtected(constructor.getModifiers())) {
return;
}
}
failWithMessage("Expected %s to have a protected constructor", actual);
}
/**
* Asserts that the actual class has no public constructor.
*
* @throws AssertionError if {@code actual} has a public constructor.
*/
private void checkHasNoPublicConstructor() {
for (Constructor> constructor : actual.getDeclaredConstructors()) {
if (isPublic(constructor.getModifiers())) {
failWithMessage("Expected %s to not have a public constructor", actual);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy