diff --git a/pom.xml b/pom.xml index e65c1c6a..53d60b85 100644 --- a/pom.xml +++ b/pom.xml @@ -22,7 +22,7 @@ org.apache.commons commons-lang3 - 3.1 + 3.5 commons-cli @@ -32,7 +32,8 @@ com.google.guava guava - 18.0 + + 20.0 ch.qos.logback @@ -52,6 +53,21 @@ 4.11 test + + + commons-io + commons-io + 2.5 + test + + + + + com.google.testing.compile + compile-testing + 0.11 + test + @@ -105,7 +121,7 @@ - + org.jacoco jacoco-maven-plugin @@ -121,6 +137,9 @@ maven-surefire-plugin ${argLine} + + false diff --git a/src/main/java/org/assertj/assertions/generator/AssertionGenerator.java b/src/main/java/org/assertj/assertions/generator/AssertionGenerator.java index 75edeff9..bf142127 100644 --- a/src/main/java/org/assertj/assertions/generator/AssertionGenerator.java +++ b/src/main/java/org/assertj/assertions/generator/AssertionGenerator.java @@ -12,12 +12,13 @@ */ package org.assertj.assertions.generator; +import com.google.common.reflect.TypeToken; +import org.assertj.assertions.generator.description.ClassDescription; + import java.io.File; import java.io.IOException; import java.util.Set; -import org.assertj.assertions.generator.description.ClassDescription; - public interface AssertionGenerator { @@ -127,7 +128,7 @@ public interface AssertionGenerator { * containing the file for the concrete final assertion. * @throws IOException if something went wrong when creating the assertion files. */ - File[] generateHierarchicalCustomAssertionFor(ClassDescription classDescription, Set> allClasses) throws IOException; + File[] generateHierarchicalCustomAssertionFor(ClassDescription classDescription, Set> allClasses) throws IOException; /** * Builds and returns the custom assertion java file content for the given {@link ClassDescription}. @@ -240,7 +241,7 @@ public interface AssertionGenerator { * @throws RuntimeException * if something went wrong when creating the assertion content. */ - String[] generateHierarchicalCustomAssertionContentFor(ClassDescription classDescription, Set> allClasses); + String[] generateHierarchicalCustomAssertionContentFor(ClassDescription classDescription, Set> allClasses); /** * Registers a template in the internal TemplateRegistry so that customers can override default templates. diff --git a/src/main/java/org/assertj/assertions/generator/AssertionsEntryPointGenerator.java b/src/main/java/org/assertj/assertions/generator/AssertionsEntryPointGenerator.java index 619c1fd9..555001e3 100644 --- a/src/main/java/org/assertj/assertions/generator/AssertionsEntryPointGenerator.java +++ b/src/main/java/org/assertj/assertions/generator/AssertionsEntryPointGenerator.java @@ -12,13 +12,12 @@ */ package org.assertj.assertions.generator; +import org.assertj.assertions.generator.description.ClassDescription; + import java.io.File; import java.io.IOException; import java.util.Set; -import org.assertj.assertions.generator.AssertionsEntryPointType; -import org.assertj.assertions.generator.description.ClassDescription; - public interface AssertionsEntryPointGenerator { /** @@ -34,7 +33,7 @@ public interface AssertionsEntryPointGenerator { * a.b.c. * * @param classDescriptionSet the set of ClassDescription we want to generate an entry point for. - * @param assertionsEntryPointType the type of entry point class to generate + * @param assertionsEntryPointType the valueType of entry point class to generate * @param entryPointClassPackage the package of the generated entry point class * @return the assertions entry point class content */ diff --git a/src/main/java/org/assertj/assertions/generator/BaseAssertionGenerator.java b/src/main/java/org/assertj/assertions/generator/BaseAssertionGenerator.java index 39879ebf..5e583921 100644 --- a/src/main/java/org/assertj/assertions/generator/BaseAssertionGenerator.java +++ b/src/main/java/org/assertj/assertions/generator/BaseAssertionGenerator.java @@ -12,32 +12,28 @@ */ package org.assertj.assertions.generator; +import com.google.common.reflect.TypeToken; import org.assertj.assertions.generator.Template.Type; import org.assertj.assertions.generator.description.ClassDescription; import org.assertj.assertions.generator.description.DataDescription; import org.assertj.assertions.generator.description.FieldDescription; import org.assertj.assertions.generator.description.GetterDescription; -import org.assertj.assertions.generator.description.TypeName; +import org.assertj.assertions.generator.util.ClassUtil; import java.io.File; import java.io.FileWriter; import java.io.IOException; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashSet; -import java.util.Set; -import java.util.SortedSet; -import java.util.TreeSet; +import java.lang.reflect.Method; +import java.nio.file.Paths; +import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import static java.lang.String.format; -import static org.apache.commons.lang3.StringUtils.capitalize; -import static org.apache.commons.lang3.StringUtils.isEmpty; -import static org.apache.commons.lang3.StringUtils.remove; -import static org.apache.commons.lang3.StringUtils.replace; +import static org.apache.commons.lang3.StringUtils.*; import static org.assertj.assertions.generator.Template.Type.ASSERT_CLASS; +@SuppressWarnings("WeakerAccess") public class BaseAssertionGenerator implements AssertionGenerator, AssertionsEntryPointGenerator { static final String ABSTRACT_ASSERT_CLASS_PREFIX = "Abstract"; @@ -59,6 +55,7 @@ public class BaseAssertionGenerator implements AssertionGenerator, AssertionsEnt private static final String PROPERTY_WITH_SAFE = "${property_safe}"; private static final String PACKAGE = "${package}"; private static final String PROPERTY_TYPE = "${propertyType}"; + private static final String PROPERTY_TYPE_PARAM = "${propertyType_parameter}"; private static final String PROPERTY_SIMPLE_TYPE = "${propertySimpleType}"; private static final String PROPERTY_ASSERT_TYPE = "${propertyAssertType}"; private static final String CLASS_TO_ASSERT = "${class_to_assert}"; @@ -72,10 +69,10 @@ public class BaseAssertionGenerator implements AssertionGenerator, AssertionsEnt private static final String IMPORTS = "${imports}"; private static final String THROWS = "${throws}"; private static final String THROWS_JAVADOC = "${throws_javadoc}"; - private static final String LINE_SEPARATOR = System.getProperty("line.separator"); + private static final String LINE_SEPARATOR = "\n"; // assertions classes are generated in their package directory starting from targetBaseDirectory. // ex : com.nba.Player -> targetBaseDirectory/com/nba/PlayerAssert.java - private String targetBaseDirectory = "."; + private File targetBaseDirectory = Paths.get(".").toFile(); private TemplateRegistry templateRegistry;// the pattern to search for /** @@ -117,13 +114,12 @@ public BaseAssertionGenerator(String templatesDirectory) throws IOException { templateRegistry = DefaultTemplateRegistryProducer.create(templatesDirectory); } - public void setDirectoryWhereAssertionFilesAreGenerated(String targetBaseDirectory) { + public void setDirectoryWhereAssertionFilesAreGenerated(File targetBaseDirectory) { this.targetBaseDirectory = targetBaseDirectory; } @Override public File generateCustomAssertionFor(ClassDescription classDescription) throws IOException { - // Assertion content String assertionFileContent = generateCustomAssertionContentFor(classDescription); // finally create the assertion file, located in its package directory starting from targetBaseDirectory @@ -134,7 +130,7 @@ public File generateCustomAssertionFor(ClassDescription classDescription) throws } @Override - public File[] generateHierarchicalCustomAssertionFor(ClassDescription classDescription, Set> allClasses) + public File[] generateHierarchicalCustomAssertionFor(ClassDescription classDescription, Set> allClasses) throws IOException { // Assertion content @@ -153,49 +149,47 @@ public File[] generateHierarchicalCustomAssertionFor(ClassDescription classDescr @Override public String[] generateHierarchicalCustomAssertionContentFor(ClassDescription classDescription, - Set> allClasses) { + Set> allClasses) { // use abstract class template first String abstractClassTemplateContent = templateRegistry.getTemplate(Type.ABSTRACT_ASSERT_CLASS).getContent(); StringBuilder abstractAssertClassContentBuilder = new StringBuilder(abstractClassTemplateContent); // generate assertion method for each property with a public getter - abstractAssertClassContentBuilder.append(generateAssertionsForDeclaredGettersOf(classDescription)); - abstractAssertClassContentBuilder.append(generateAssertionsForDeclaredPublicFieldsOf(classDescription)); + generateAssertionsForDeclaredGettersOf(abstractAssertClassContentBuilder, classDescription); + generateAssertionsForDeclaredPublicFieldsOf(abstractAssertClassContentBuilder, classDescription); // close class with } abstractAssertClassContentBuilder.append(LINE_SEPARATOR).append("}").append(LINE_SEPARATOR); // use concrete class template for the subclass of the generated abstract assert String concreteAssertClassContent = templateRegistry.getTemplate(Type.HIERARCHICAL_ASSERT_CLASS).getContent(); - StringBuilder concreteAssertClassContentBuilder = new StringBuilder(concreteAssertClassContent); // return a String array with the actual generated of the assertion class hierarchy String[] assertionClassesContent = new String[2]; assertionClassesContent[0] = fillAssertClassTemplate(abstractAssertClassContentBuilder.toString(), classDescription, allClasses, false); - assertionClassesContent[1] = fillAssertClassTemplate(concreteAssertClassContentBuilder.toString(), + assertionClassesContent[1] = fillAssertClassTemplate(concreteAssertClassContent, classDescription, null, true); return assertionClassesContent; } private String fillAssertClassTemplate(String template, ClassDescription classDescription, - Set> classesHierarchy, boolean concrete) { + Set> classesHierarchy, boolean concrete) { // Add any AssertJ needed imports only, other types are used with their fully qualified names to avoid a compilation // error when two types have the same - TreeSet assertjImports = new TreeSet(); - if (template.contains("Assertions.")) assertjImports.add(new TypeName("org.assertj.core.api.Assertions")); - if (template.contains("Objects.")) assertjImports.add(new TypeName("org.assertj.core.util.Objects")); - if (template.contains("Iterables.")) assertjImports.add(new TypeName("org.assertj.core.internal.Iterables")); + TreeSet assertjImports = new TreeSet<>(); + if (template.contains("Assertions.")) assertjImports.add("org.assertj.core.api.Assertions"); + if (template.contains("Objects.")) assertjImports.add("org.assertj.core.util.Objects"); + if (template.contains("Iterables.")) assertjImports.add("org.assertj.core.internal.Iterables"); - final TypeName superAssertionClass; + final String superAssertionClassName; // Add assertion supertype to imports if needed if (classesHierarchy == null || !classesHierarchy.contains(classDescription.getSuperType())) { - superAssertionClass = new TypeName("org.assertj.core.api.AbstractObjectAssert"); + superAssertionClassName = "org.assertj.core.api.AbstractObjectAssert"; } else { - final TypeName superTypeName = new TypeName(classDescription.getSuperType()); - superAssertionClass = new TypeName(abstractAssertClassNameOf(superTypeName), superTypeName.getPackageName()); + superAssertionClassName = abstractAssertClassNameOf(classDescription.getSuperType()); } - assertjImports.add(superAssertionClass); + assertjImports.add(superAssertionClassName); final String customAssertionClass = concrete ? assertClassNameOf(classDescription) : abstractAssertClassNameOf(classDescription); @@ -207,7 +201,7 @@ private String fillAssertClassTemplate(String template, ClassDescription classDe // className could be a nested class like "OuterClass.NestedClass", in that case assert class will be // OuterClassNestedClass template = replace(template, SUPER_ASSERTION_CLASS, - superAssertionClass.getSimpleNameWithOuterClassNotSeparatedByDots()); + ClassUtil.getTypeNameWithoutDots(superAssertionClassName)); template = replace(template, CLASS_TO_ASSERT, classDescription.getClassNameWithOuterClass()); template = replace(template, SELF_TYPE, selfType); template = replace(template, MYSELF, myself); @@ -228,8 +222,8 @@ public String generateCustomAssertionContentFor(ClassDescription classDescriptio StringBuilder assertionFileContentBuilder = new StringBuilder(classTemplateContent); // generate assertion method for each property with a public getter - assertionFileContentBuilder.append(generateAssertionsForGettersOf(classDescription)); - assertionFileContentBuilder.append(generateAssertionsForPublicFieldsOf(classDescription)); + generateAssertionsForGettersOf(assertionFileContentBuilder, classDescription); + generateAssertionsForPublicFieldsOf(assertionFileContentBuilder, classDescription); // close class with } assertionFileContentBuilder.append(LINE_SEPARATOR).append("}").append(LINE_SEPARATOR); @@ -354,10 +348,10 @@ private File createAssertionsFileFor(final Set classDescriptio private String generateAssertionEntryPointMethodsFor(final Set classDescriptionSet, Template assertionEntryPointMethodTemplate) { // sort ClassDescription according to their class name. - SortedSet sortedClassDescriptionSet = new TreeSet(classDescriptionSet); + SortedSet sortedClassDescriptionSet = new TreeSet<>(classDescriptionSet); // generate for each classDescription the entry point method, e.g. assertThat(MyClass) or then(MyClass) StringBuilder allAssertThatsContentBuilder = new StringBuilder(); - final String lineSeparator = System.getProperty("line.separator"); + final char lineSeparator = '\n'; for (ClassDescription classDescription : sortedClassDescriptionSet) { String assertionEntryPointMethodContent = assertionEntryPointMethodTemplate.getContent(); // resolve class assert (ex: PlayerAssert) @@ -374,7 +368,7 @@ private String generateAssertionEntryPointMethodsFor(final Set } private String determineBestEntryPointsAssertionsClassPackage(final Set classDescriptionSet) { - SortedSet packages = new TreeSet(new Comparator() { + SortedSet packages = new TreeSet<>(new Comparator() { @Override public int compare(final String o1, final String o2) { return o1.length() - o2.length(); @@ -389,18 +383,18 @@ public int compare(final String o1, final String o2) { } private static String assertClassNameOf(ClassDescription classDescription) { - return assertClassNameOf(classDescription.getTypeName()); + return assertClassNameOf(classDescription.getType()); } - private static String assertClassNameOf(TypeName type) { - return type.getSimpleNameWithOuterClassNotSeparatedByDots() + ASSERT_CLASS_SUFFIX; + private static String assertClassNameOf(TypeToken type) { + return ClassUtil.getTypeNameWithoutDots(ClassUtil.getTypeDeclaration(type, false, false)) + ASSERT_CLASS_SUFFIX; } private static String abstractAssertClassNameOf(ClassDescription classDescription) { - return abstractAssertClassNameOf(classDescription.getTypeName()); + return abstractAssertClassNameOf(classDescription.getType()); } - private static String abstractAssertClassNameOf(TypeName type) { + private static String abstractAssertClassNameOf(TypeToken type) { return ABSTRACT_ASSERT_CLASS_PREFIX + assertClassNameOf(type); } @@ -419,70 +413,73 @@ private String getDirectoryPathCorrespondingToPackage(final String packageName) return targetBaseDirectory + File.separator + packageName.replace('.', File.separatorChar); } - private static String listNeededImports(Set typesToImport, String classPackage) { + private static String listNeededImports(Set typesToImport, String classPackage) { StringBuilder importsBuilder = new StringBuilder(); - for (TypeName type : typesToImport) { - if (!type.isPrimitive() && !type.belongsToJavaLangPackage() && !type.getPackageName().equals(classPackage)) { - importsBuilder.append(format(IMPORT_LINE, type, LINE_SEPARATOR)); + for (String type : typesToImport) { + try { + Class clazz = Class.forName(type); + if (!clazz.isPrimitive() && !ClassUtil.isJavaLangType(clazz) + && !ClassUtil.isInnerPackageOf(type, classPackage) && !Objects.equals(classPackage, type)) { + importsBuilder.append(format(IMPORT_LINE, type, LINE_SEPARATOR)); + } + } catch (ClassNotFoundException cfne) { + // continue iteration; } } return importsBuilder.toString(); } - protected String generateAssertionsForGettersOf(ClassDescription classDescription) { - return generateAssertionsForGetters(classDescription.getGettersDescriptions(), classDescription); + protected void generateAssertionsForGettersOf(StringBuilder contentBuilder, ClassDescription classDescription) { + generateAssertionsForGetters(contentBuilder, classDescription.getGettersDescriptions(), classDescription); } - protected String generateAssertionsForDeclaredGettersOf(ClassDescription classDescription) { - return generateAssertionsForGetters(classDescription.getDeclaredGettersDescriptions(), classDescription); + protected void generateAssertionsForDeclaredGettersOf(StringBuilder contentBuilder, ClassDescription classDescription) { + generateAssertionsForGetters(contentBuilder, classDescription.getDeclaredGettersDescriptions(), classDescription); } - protected String generateAssertionsForGetters(Set getters, ClassDescription classDescription) { - StringBuilder assertionsForGetters = new StringBuilder(); + protected void generateAssertionsForGetters(StringBuilder assertionsForGetters, Set getters, ClassDescription classDescription) { for (GetterDescription getter : getters) { String assertionContent = assertionContentForProperty(getter, classDescription); assertionsForGetters.append(assertionContent).append(LINE_SEPARATOR); } - return assertionsForGetters.toString(); } - protected String generateAssertionsForPublicFieldsOf(ClassDescription classDescription) { - return generateAssertionsForPublicFields(classDescription.getFieldsDescriptions(), classDescription); + protected void generateAssertionsForPublicFieldsOf(StringBuilder contentBuilder, ClassDescription classDescription) { + generateAssertionsForPublicFields(contentBuilder, classDescription.getFieldsDescriptions(), classDescription); } - protected String generateAssertionsForDeclaredPublicFieldsOf(ClassDescription classDescription) { - return generateAssertionsForPublicFields(classDescription.getDeclaredFieldsDescriptions(), classDescription); + protected void generateAssertionsForDeclaredPublicFieldsOf(StringBuilder contentBuilder, ClassDescription classDescription) { + generateAssertionsForPublicFields(contentBuilder, classDescription.getDeclaredFieldsDescriptions(), classDescription); } - protected String generateAssertionsForPublicFields(Set fields, ClassDescription classDescription) { - StringBuilder assertionsForPublicFields = new StringBuilder(); + protected void generateAssertionsForPublicFields(StringBuilder assertionsForPublicFields, Set fields, ClassDescription classDescription) { for (FieldDescription field : fields) { String assertionContent = assertionContentForField(field, classDescription); assertionsForPublicFields.append(assertionContent).append(LINE_SEPARATOR); } - return assertionsForPublicFields.toString(); } private String assertionContentForField(FieldDescription field, ClassDescription classDescription) { - final String fieldName = field.getName(); - final String fieldNameCap = capitalize(field.getName()); - if (classDescription.getGettersDescriptions().contains(new GetterDescription(fieldName, "get" + fieldNameCap, - field.getTypeDescription(), - Collections. emptyList()))) { + + // Check for getter existing + GetterDescription getter = classDescription.findGetterDescriptionForField(field); + if (getter != null) { return ""; } + + final String fieldName = field.getName(); String assertionContent = baseAssertionContentFor(field, classDescription); // we reuse template for properties to have consistent assertions for property and field but change the way we get // the value since it's a field and not a property: - assertionContent = assertionContent.replace("${getter}()", "${property}"); + assertionContent = assertionContent.replace("${getter}()", PROPERTY_WITH_LOWERCASE_FIRST_CHAR); // - remove also ${throws} and ${throws_javadoc} since it does not make any sense for a field assertionContent = remove(assertionContent, "${throws}"); assertionContent = remove(assertionContent, "${throws_javadoc}"); // replace ${Property} and ${property} by field name (starting with uppercase/lowercase) if (field.isPredicate()) { - assertionContent = assertionContent.replace("actual." + PREDICATE + "()", "actual." + field.getOriginalMember()); + assertionContent = assertionContent.replace("actual." + PREDICATE + "()", "actual." + field.getOriginalMember().getName()); assertionContent = assertionContent.replace(PREDICATE_FOR_JAVADOC, field.getPredicateForJavadoc()); assertionContent = assertionContent.replace(NEGATIVE_PREDICATE_FOR_JAVADOC, @@ -498,20 +495,22 @@ Collections. emptyList()))) { assertionContent = replace(assertionContent, PREDICATE, field.getPredicate()); assertionContent = replace(assertionContent, PREDICATE_NEG, field.getNegativePredicate()); } - assertionContent = replace(assertionContent, PROPERTY_WITH_UPPERCASE_FIRST_CHAR, fieldNameCap); + assertionContent = replace(assertionContent, PROPERTY_WITH_UPPERCASE_FIRST_CHAR, capitalize(field.getName())); assertionContent = replace(assertionContent, PROPERTY_SIMPLE_TYPE, - field.getTypeName()); + field.getTypeName(false, false)); assertionContent = replace(assertionContent, PROPERTY_ASSERT_TYPE, field.getAssertTypeName(classDescription.getPackageName())); assertionContent = replace(assertionContent, PROPERTY_TYPE, - field.getFullyQualifiedTypeNameIfNeeded(classDescription.getPackageName())); + field.getFullyQualifiedTypeNameIfNeeded(classDescription.getPackageName(), false)); + assertionContent = replace(assertionContent, PROPERTY_TYPE_PARAM, + field.getFullyQualifiedTypeNameIfNeeded(classDescription.getPackageName(), true)); assertionContent = replace(assertionContent, PROPERTY_WITH_LOWERCASE_FIRST_CHAR, fieldName); // It should not be possible to have a field that is a keyword - compiler won't allow it. assertionContent = replace(assertionContent, PROPERTY_WITH_SAFE, fieldName); return assertionContent; } - static private final Set JAVA_KEYWORDS = new HashSet(); + static private final Set JAVA_KEYWORDS = new HashSet<>(); static { String[] keywords = new String[] { @@ -582,7 +581,7 @@ private String assertionContentForProperty(GetterDescription getter, ClassDescri assertionContent = declareExceptions(getter, assertionContent, classDescription); - String propertyName = getter.getPropertyName(); + String propertyName = getter.getName(); if (getter.isPredicate()) { assertionContent = assertionContent.replace(PREDICATE_FOR_JAVADOC, getter.getPredicateForJavadoc()); @@ -596,17 +595,19 @@ private String assertionContentForProperty(GetterDescription getter, ClassDescri getter.getNegativePredicateForErrorMessagePart1()); assertionContent = assertionContent.replace(NEGATIVE_PREDICATE_FOR_FOR_ERROR_MESSAGE_PART2, getter.getNegativePredicateForErrorMessagePart2()); - assertionContent = replace(assertionContent, PREDICATE, getter.getOriginalMember()); + assertionContent = replace(assertionContent, PREDICATE, getter.getOriginalMember().getName()); assertionContent = replace(assertionContent, PREDICATE_NEG, getter.getNegativePredicate()); } - assertionContent = replace(assertionContent, PROPERTY_GETTER_CALL, getter.getOriginalMember()); + assertionContent = replace(assertionContent, PROPERTY_GETTER_CALL, getter.getOriginalMember().getName()); assertionContent = replace(assertionContent, PROPERTY_WITH_UPPERCASE_FIRST_CHAR, capitalize(propertyName)); assertionContent = replace(assertionContent, PROPERTY_SIMPLE_TYPE, - getter.getTypeName()); + getter.getTypeName(false, false)); assertionContent = replace(assertionContent, PROPERTY_ASSERT_TYPE, getter.getAssertTypeName(classDescription.getPackageName())); assertionContent = replace(assertionContent, PROPERTY_TYPE, - getter.getFullyQualifiedTypeNameIfNeeded(classDescription.getPackageName())); + getter.getFullyQualifiedTypeNameIfNeeded(classDescription.getPackageName(), false)); + assertionContent = replace(assertionContent, PROPERTY_TYPE_PARAM, + getter.getFullyQualifiedTypeNameIfNeeded(classDescription.getPackageName(), true)); assertionContent = replace(assertionContent, PROPERTY_WITH_LOWERCASE_FIRST_CHAR, propertyName); assertionContent = replace(assertionContent, PROPERTY_WITH_SAFE, getSafeProperty(propertyName)); return assertionContent; @@ -646,7 +647,7 @@ private String baseAssertionContentFor(DataDescription fieldOrProperty, ClassDes Type type = fieldOrProperty.isPrimitiveWrapperType() ? Type.HAS_FOR_CHARACTER : Type.HAS_FOR_CHAR; assertionContent = templateRegistry.getTemplate(type).getContent(); } else if (fieldOrProperty.isPrimitiveType()) { - // use case : boolean getFoo -> not a predicate, but a primitive type + // use case : boolean getFoo -> not a predicate, but a primitive valueType Type type = fieldOrProperty.isPrimitiveWrapperType() ? Type.HAS_FOR_PRIMITIVE_WRAPPER : Type.HAS_FOR_PRIMITIVE; assertionContent = templateRegistry.getTemplate(type).getContent(); } @@ -668,7 +669,7 @@ private Type determinePredicateType(final DataDescription fieldOrProperty, final private boolean hasAlreadyNegativePredicate(final DataDescription fieldOrProperty, final ClassDescription classDescription) { for (final GetterDescription getterDescription : classDescription.getGettersDescriptions()) { - if (getterDescription.getOriginalMember().equals(fieldOrProperty.getNegativePredicate())) return true; + if (getterDescription.getOriginalMember().getName().equals(fieldOrProperty.getNegativePredicate())) return true; } return false; } @@ -686,11 +687,11 @@ private String declareExceptions(GetterDescription getter, String assertionConte StringBuilder throwsClause = new StringBuilder(); StringBuilder throwsJavaDoc = new StringBuilder(); boolean first = true; - for (TypeName exception : getter.getExceptions()) { + for (TypeToken exception : getter.getExceptions()) { if (first) throwsClause.append("throws "); else throwsClause.append(", "); first = false; - String exceptionName = exception.getFullyQualifiedTypeNameIfNeeded(classDescription.getPackageName()); + String exceptionName = ClassUtil.getTypeDeclarationWithinPackage(exception, classDescription.getPackageName(), false); throwsClause.append(exceptionName); throwsJavaDoc.append(LINE_SEPARATOR).append(" * @throws ").append(exceptionName); throwsJavaDoc.append(" if actual.").append("${getter}() throws one."); @@ -703,13 +704,17 @@ private String declareExceptions(GetterDescription getter, String assertionConte } private void fillFile(String customAssertionContent, File assertionJavaFile) throws IOException { - try (FileWriter fileWriter = new FileWriter(assertionJavaFile)) { + try (FileWriter fileWriter = new FileWriter(assertionJavaFile, false)) { fileWriter.write(customAssertionContent); } } private File createFile(String fileContent, String fileName, String targetDirectory) throws IOException { File file = new File(targetDirectory, fileName); + + // Ignore the result as it only returns false when the file existed previously + // which is not _wrong_. + //noinspection ResultOfMethodCallIgnored file.createNewFile(); fillFile(fileContent, file); return file; @@ -720,6 +725,9 @@ private static boolean noClassDescriptionsGiven(final Set clas } private static void buildTargetDirectory(String targetDirectory) { + // Ignore the result as it only returns true iff the dir was created, false is + // not bad. + //noinspection ResultOfMethodCallIgnored new File(targetDirectory).mkdirs(); } diff --git a/src/main/java/org/assertj/assertions/generator/cli/AssertionGeneratorLauncher.java b/src/main/java/org/assertj/assertions/generator/cli/AssertionGeneratorLauncher.java index ddd8a654..d4b5ab02 100644 --- a/src/main/java/org/assertj/assertions/generator/cli/AssertionGeneratorLauncher.java +++ b/src/main/java/org/assertj/assertions/generator/cli/AssertionGeneratorLauncher.java @@ -12,25 +12,21 @@ */ package org.assertj.assertions.generator.cli; -import static com.google.common.collect.Sets.newLinkedHashSet; -import static org.assertj.assertions.generator.util.ClassUtil.collectClasses; - -import java.io.File; -import java.io.IOException; -import java.util.Set; - -import org.apache.commons.cli.BasicParser; -import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.CommandLineParser; -import org.apache.commons.cli.HelpFormatter; -import org.apache.commons.cli.Options; -import org.apache.commons.cli.ParseException; +import com.google.common.reflect.TypeToken; +import org.apache.commons.cli.*; import org.assertj.assertions.generator.BaseAssertionGenerator; import org.assertj.assertions.generator.description.ClassDescription; import org.assertj.assertions.generator.description.converter.ClassToClassDescriptionConverter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.File; +import java.io.IOException; +import java.util.Set; + +import static com.google.common.collect.Sets.newLinkedHashSet; +import static org.assertj.assertions.generator.util.ClassUtil.collectClasses; + public class AssertionGeneratorLauncher { @@ -51,7 +47,7 @@ public static void main(String[] args) throws IOException { return; } - Set> classes = collectClasses(line.getArgs()); + Set> classes = collectClasses(line.getArgs()); if (line.hasOption('H')) { generateHierarchicalAssertions(classes); @@ -71,34 +67,34 @@ private static void printHelp(Options options) { help.printHelp(cmdLine, "Generate AssertJ-style assertions for the specified classes", options, "The list of classes can either be package names (which includes all packages in the class) or fully-qualified class names."); } - private static void generateHierarchicalAssertions(Set> classes) throws IOException { + private static void generateHierarchicalAssertions(Set> types) throws IOException { // Create a hashset of the classes for efficient lookup. - Set> classSet = newLinkedHashSet(classes); - logger.info("Generating hierarchical assertions for classes {}", classes); + Set> typeSet = newLinkedHashSet(types); + logger.info("Generating hierarchical assertions for classes {}", types); BaseAssertionGenerator customAssertionGenerator = new BaseAssertionGenerator(); - for (Class clazz : classes) { - logger.info("Generating hierarchical assertions for class : {}", clazz.getName()); - File[] customAssertionFiles = customAssertionGenerator.generateHierarchicalCustomAssertionFor(toClassDescription(clazz), classSet); - logger.info("Generated {} hierarchical assertions files -> {}, {}", clazz.getSimpleName(), + for (TypeToken type : types) { + logger.info("Generating hierarchical assertions for class : {}", type); + File[] customAssertionFiles = customAssertionGenerator.generateHierarchicalCustomAssertionFor(toClassDescription(type), typeSet); + logger.info("Generated {} hierarchical assertions files -> {}, {}", type, customAssertionFiles[0].getAbsolutePath(), customAssertionFiles[1].getAbsolutePath()); } } - private static void generateFlatAssertions(Set> classes) throws IOException { - logger.info("Generating assertions for classes {}", classes); + private static void generateFlatAssertions(Set> types) throws IOException { + logger.info("Generating assertions for types {}", types); BaseAssertionGenerator customAssertionGenerator = new BaseAssertionGenerator(); - for (Class clazz : classes) { - logger.info("Generating assertions for class : {}", clazz.getName()); - File customAssertionFile = customAssertionGenerator.generateCustomAssertionFor(toClassDescription(clazz)); - logger.info("Generated {} assertions file -> {}", clazz.getSimpleName(), + for (TypeToken type : types) { + logger.info("Generating assertions for class : {}", type); + File customAssertionFile = customAssertionGenerator.generateCustomAssertionFor(toClassDescription(type)); + logger.info("Generated {} assertions file -> {}", type, customAssertionFile.getAbsolutePath()); } } - private static ClassDescription toClassDescription(Class clazz) { - return classDescriptionConverter.convertToClassDescription(clazz); + private static ClassDescription toClassDescription(TypeToken type) { + return classDescriptionConverter.convertToClassDescription(type); } } diff --git a/src/main/java/org/assertj/assertions/generator/description/ClassDescription.java b/src/main/java/org/assertj/assertions/generator/description/ClassDescription.java index d732a494..586d6a66 100644 --- a/src/main/java/org/assertj/assertions/generator/description/ClassDescription.java +++ b/src/main/java/org/assertj/assertions/generator/description/ClassDescription.java @@ -12,9 +12,12 @@ */ package org.assertj.assertions.generator.description; -import java.util.Collection; -import java.util.Set; -import java.util.TreeSet; +import com.google.common.reflect.TypeToken; +import org.apache.commons.lang3.StringUtils; +import org.assertj.assertions.generator.util.ClassUtil; +import org.assertj.assertions.generator.util.StringUtil; + +import java.util.*; /** * @@ -29,40 +32,41 @@ public class ClassDescription implements Comparable { private Set fieldsDescriptions; private Set declaredGettersDescriptions; private Set declaredFieldsDescriptions; - private TypeName classTypeName; - private Class superType; + private TypeToken type; + private TypeToken superType; - public ClassDescription(TypeName typeName) { + public ClassDescription(TypeToken type) { super(); - this.classTypeName = typeName; - this.gettersDescriptions = new TreeSet(); - this.fieldsDescriptions = new TreeSet(); - this.declaredGettersDescriptions = new TreeSet(); - this.declaredFieldsDescriptions = new TreeSet(); + this.type = type; + this.superType = null; + this.gettersDescriptions = new TreeSet<>(); + this.fieldsDescriptions = new TreeSet<>(); + this.declaredGettersDescriptions = new TreeSet<>(); + this.declaredFieldsDescriptions = new TreeSet<>(); } public String getClassName() { - return classTypeName.getSimpleName(); + return type.getRawType().getName(); } public String getFullyQualifiedClassName() { - return classTypeName.getFullyQualifiedClassName(); + return ClassUtil.getTypeDeclaration(type, false, true); } - public TypeName getTypeName() { - return classTypeName; + public TypeToken getType() { + return type; } public String getClassNameWithOuterClass() { - return classTypeName.getSimpleNameWithOuterClass(); + return ClassUtil.getTypeDeclaration(type, false, false); } public String getClassNameWithOuterClassNotSeparatedByDots() { - return classTypeName.getSimpleNameWithOuterClassNotSeparatedByDots(); + return ClassUtil.getTypeNameWithoutDots(getClassNameWithOuterClass()); //classTypeName.getSimpleNameWithOuterClassNotSeparatedByDots(); } public String getPackageName() { - return classTypeName.getPackageName(); + return type.getRawType().getPackage().getName(); } public Set getGettersDescriptions() { @@ -96,10 +100,54 @@ public void addDeclaredGetterDescriptions(Collection declared public void addDeclaredFieldDescriptions(Set declaredFieldDescriptions) { this.declaredFieldsDescriptions.addAll(declaredFieldDescriptions); } + + public GetterDescription findGetterDescriptionForField(FieldDescription base) { + + final String capName = StringUtils.capitalize(base.getName()); + if (ClassUtil.isBoolean(base.getValueType())) { + // deal with predicates + + // Build a map for better look-up + Map fieldMap = new HashMap<>(); + for (GetterDescription getter: this.gettersDescriptions) { + fieldMap.put(getter.getOriginalMember().getName(), getter); + } + for (GetterDescription getter: this.declaredGettersDescriptions) { + fieldMap.put(getter.getOriginalMember().getName(), getter); + } + + for (String prefix: ClassUtil.PREDICATE_PREFIXES.keySet()) { + String propName = prefix + capName; + + GetterDescription getterDesc = fieldMap.get(propName); + if (getterDesc != null) { + return getterDesc; + } + } + } else { + + String propName = "get" + capName; + + for (GetterDescription desc: this.gettersDescriptions) { + if (Objects.equals(desc.getOriginalMember().getName(), propName)) { + return desc; + } + } + + for (GetterDescription desc: this.declaredGettersDescriptions) { + if (Objects.equals(desc.getOriginalMember().getName(), propName)) { + return desc; + } + } + } + + // wasn't found + return null; + } @Override public String toString() { - return "ClassDescription [classTypeName=" + classTypeName + "]"; + return "ClassDescription [valueType=" + type + "]"; } @Override @@ -108,25 +156,28 @@ public boolean equals(final Object o) { if (!(o instanceof ClassDescription)) return false; final ClassDescription that = (ClassDescription) o; - if (classTypeName != null ? !classTypeName.equals(that.classTypeName) : that.classTypeName != null) return false; - return true; + return (Objects.equals(type, that.type)); } @Override public int hashCode() { - return classTypeName != null ? classTypeName.hashCode() : 0; + return Objects.hash(type); } @Override public int compareTo(ClassDescription o) { - return classTypeName.compareTo(o.classTypeName); + return type.getRawType().getName().compareTo(o.type.getRawType().getName()); } - public Class getSuperType() { + public TypeToken getSuperType() { return superType; } + @SuppressWarnings("unchecked") public void setSuperType(Class superType) { - this.superType = superType; + // TypeToken#getSupertype(..) checks to make sure it is a super type + if (superType != null) { + this.superType = type.getSupertype((Class)superType); + } } } diff --git a/src/main/java/org/assertj/assertions/generator/description/DataDescription.java b/src/main/java/org/assertj/assertions/generator/description/DataDescription.java index bcf429f8..80cfa084 100644 --- a/src/main/java/org/assertj/assertions/generator/description/DataDescription.java +++ b/src/main/java/org/assertj/assertions/generator/description/DataDescription.java @@ -12,17 +12,22 @@ */ package org.assertj.assertions.generator.description; -import static org.apache.commons.lang3.StringUtils.removeStart; -import static org.assertj.assertions.generator.util.ClassUtil.getNegativePredicateFor; -import static org.assertj.assertions.generator.util.ClassUtil.getPredicatePrefix; -import static org.assertj.assertions.generator.util.StringUtil.camelCaseToWords; +import com.google.common.base.Objects; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Ordering; +import com.google.common.primitives.Ints; +import com.google.common.primitives.Primitives; +import com.google.common.reflect.TypeToken; +import org.assertj.assertions.generator.util.ClassUtil; +import java.lang.reflect.Member; import java.util.List; import java.util.Map; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Ordering; -import com.google.common.primitives.Ints; +import static org.apache.commons.lang3.StringUtils.removeStart; +import static org.assertj.assertions.generator.util.ClassUtil.getNegativePredicateFor; +import static org.assertj.assertions.generator.util.ClassUtil.getPredicatePrefix; +import static org.assertj.assertions.generator.util.StringUtil.camelCaseToWords; /** * base class to describe a field or a property/getter @@ -30,8 +35,8 @@ public abstract class DataDescription { protected final String name; - protected final String originalMember; - protected final TypeDescription typeDescription; + protected final Member originalMember; + protected final TypeToken valueType; public static final Map PREDICATE_PREFIXES_FOR_JAVADOC = new ImmutableMap.Builder().put("is", "is") @@ -39,13 +44,19 @@ public abstract class DataDescription { .put("was", "was") .put("wasNot", "was not") .put("can", "can") + .put("canBe", "can be") .put("cannot", "cannot") + .put("cannotBe", "cannot be") .put("should", "should") + .put("shouldBe", "should be") .put("shouldNot", "should not") + .put("shouldNotBe", "should not be") .put("has", "has") .put("doesNotHave", "does not have") .put("will", "will") + .put("willBe", "will be") .put("willNot", "will not") + .put("willNotBe", "will not be") .build(); public static final Map PREDICATE_PREFIXES_FOR_ERROR_MESSAGE_PART1 = @@ -54,13 +65,19 @@ public abstract class DataDescription { .put("was", "was") .put("wasNot", "was not") .put("can", "can") + .put("canBe", "can be") .put("cannot", "cannot") + .put("cannotBe", "cannot be") .put("should", "should") + .put("shouldBe", "should be") .put("shouldNot", "should not") + .put("shouldNotBe", "should not be") .put("has", "has") .put("doesNotHave", "does not have") .put("will", "will") + .put("willBe", "will be") .put("willNot", "will not") + .put("willNotBe", "will not be") .build(); public static final Map PREDICATE_PREFIXES_FOR_ERROR_MESSAGE_PART2 = @@ -69,13 +86,19 @@ public abstract class DataDescription { .put("was", "was not") .put("wasNot", "was") .put("can", "cannot") + .put("canBe", "is not") .put("cannot", "can") + .put("cannotBe", "is not") .put("should", "should not") + .put("shouldBe", "is not") .put("shouldNot", "should") + .put("shouldNotBe", "should be") .put("has", "does not have") .put("doesNotHave", "has") .put("will", "will not") + .put("willBe", "will not be") .put("willNot", "will") + .put("willNotBe", "will be") .build(); private static final Ordering BY_BIGGER_LENGTH_ORDERING = new Ordering() { @@ -85,92 +108,110 @@ public int compare(String left, String right) { } }; - public DataDescription(String name, String originalMember, TypeDescription typeDescription) { + DataDescription(String name, Member originalMember, TypeToken type) { super(); this.name = name; this.originalMember = originalMember; - this.typeDescription = typeDescription; + this.valueType = type; } public String getName() { return name; } - public String getOriginalMember() { + public Member getOriginalMember() { return originalMember; } - public TypeDescription getTypeDescription() { - return typeDescription; + public TypeToken getValueType() { + return valueType; } - public String getTypeName() { - return typeDescription.getSimpleNameWithOuterClass(); + /** + * Get the type of the value stored by the {@link #originalMember} + * @param isFQN Whether or not to get the fully qualified name + * @param asParameter if true, this will generate a type-name that is best for + * passing as a parameter, for example, for a {@link java.util.Collection Collection} + * this would return {@code Collection<? extends String>} instead of + * just {@code String} + * @return + */ + public String getTypeName(boolean isFQN, final boolean asParameter) { + return ClassUtil.getTypeDeclaration(valueType, asParameter, isFQN); } public boolean isIterableType() { - return typeDescription.isIterable(); + return valueType.isSubtypeOf(Iterable.class); } public boolean isArrayType() { - return typeDescription.isArray(); + return valueType.isArray(); } public boolean isPrimitiveType() { - return typeDescription.isPrimitive(); + return valueType.isPrimitive(); } public boolean isRealNumberType() { - return typeDescription.isRealNumber(); + TypeToken unwrapped = valueType.unwrap(); + return unwrapped.isSubtypeOf(double.class) || unwrapped.isSubtypeOf(float.class); } public boolean isWholeNumberType() { - return typeDescription.isWholeNumber(); + TypeToken unwrapped = valueType.unwrap(); + return unwrapped.isSubtypeOf(int.class) || unwrapped.isSubtypeOf(long.class) + || unwrapped.isSubtypeOf(byte.class) || unwrapped.isSubtypeOf(short.class); } public boolean isCharType() { - return typeDescription.isChar(); + TypeToken unwrapped = valueType.unwrap(); + return unwrapped.isSubtypeOf(char.class); } public boolean isPrimitiveWrapperType() { - return typeDescription.isPrimitiveWrapper(); + return Primitives.isWrapperType(valueType.getRawType()); } public abstract boolean isPredicate(); public String getPredicate() { - return originalMember; + return originalMember.getName(); } public String getNegativePredicate() { - return getNegativePredicateFor(originalMember); + return getNegativePredicateFor(originalMember.getName()); } /** - * return the simple element type name if element type belongs to given the package and the fully qualified element - * type name otherwise. + * return the simple element valueType name if element valueType belongs to given the package and the fully qualified element + * valueType name otherwise. * * @param packageName typically the package of the enclosing Class - * @return the simple element type name if element type belongs to given the package and the fully qualified element - * type name otherwise. + * @return the simple element valueType name if element valueType belongs to given the package and the fully qualified element + * valueType name otherwise. */ public String getElementTypeName(String packageName) { - return typeDescription.getElementTypeName() == null ? null - : typeDescription.getElementTypeName().getFullyQualifiedTypeNameIfNeeded(packageName); + if (valueType.isArray()) { + return ClassUtil.getTypeDeclarationWithinPackage(valueType.getComponentType(), packageName, false); + } else if (valueType.isSubtypeOf(Iterable.class)) { + TypeToken componentType = valueType.resolveType(Iterable.class.getTypeParameters()[0]); + return ClassUtil.getTypeDeclarationWithinPackage(componentType, packageName, false); + } + + return null; } public String getElementAssertTypeName(String packageName) { - TypeName elementTypeName = typeDescription.getElementTypeName(); - return elementTypeName == null ? null - : elementTypeName.getAssertTypeName(packageName); + TypeToken elementType = valueType.getComponentType(); + return elementType == null ? null : ClassUtil.getAssertType(elementType, packageName); } - public String getFullyQualifiedTypeNameIfNeeded(String packageName) { - return typeDescription.getFullyQualifiedTypeNameIfNeeded(packageName); + public String getFullyQualifiedTypeNameIfNeeded(String packageName, final boolean asParameter) { + return ClassUtil.getTypeDeclarationWithinPackage(valueType, packageName, false); } public String getAssertTypeName(String packageName) { - return typeDescription.getAssertTypeName(packageName); + return ClassUtil.getAssertType(valueType, packageName); } public String getPredicateForJavadoc() { @@ -208,15 +249,47 @@ protected String readablePropertyName() { List prefixesSortedByBiggerLength = BY_BIGGER_LENGTH_ORDERING.immutableSortedCopy(PREDICATE_PREFIXES_FOR_JAVADOC.keySet()); for (String predicatePrefix : prefixesSortedByBiggerLength) { - if (originalMember.startsWith(predicatePrefix)) { + if (originalMember.getName().startsWith(predicatePrefix)) { // get rid of prefix - String propertyName = removeStart(originalMember, predicatePrefix); + String propertyName = removeStart(originalMember.getName(), predicatePrefix); // make it human readable return camelCaseToWords(propertyName); } } + // should not arrive here ! return for best effort. return name; } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + DataDescription that = (DataDescription) o; + return Objects.equal(name, that.name) && + Objects.equal(originalMember, that.originalMember) && + Objects.equal(valueType, that.valueType); + } + + @Override + public int hashCode() { + return Objects.hashCode(name, originalMember, valueType); + } + + @Override + public String toString() { + return getClass().getSimpleName() + "[name=" + getName() + + ", valueType=" + valueType + + ", member=" + originalMember + "]"; + } + + protected int compareTo(final DataDescription other) { + // Use the property name to remove duplicates + int cmp = getName().compareTo(other.getName()); + if (cmp == 0) { + cmp = getOriginalMember().getName().compareTo(other.getOriginalMember().getName()); + } + + return cmp; + } } \ No newline at end of file diff --git a/src/main/java/org/assertj/assertions/generator/description/FieldDescription.java b/src/main/java/org/assertj/assertions/generator/description/FieldDescription.java index 16c78397..bd09b8c8 100644 --- a/src/main/java/org/assertj/assertions/generator/description/FieldDescription.java +++ b/src/main/java/org/assertj/assertions/generator/description/FieldDescription.java @@ -12,6 +12,11 @@ */ package org.assertj.assertions.generator.description; +import com.google.common.reflect.TypeToken; +import org.assertj.assertions.generator.util.ClassUtil; + +import java.lang.reflect.Field; + import static org.apache.commons.lang3.StringUtils.capitalize; @@ -28,7 +33,7 @@ * need to know : *
    *
  • the field name, here "age"
  • - *
  • the field type
  • + *
  • the field valueType
  • *
* This class is immutable. * @@ -36,35 +41,42 @@ */ public class FieldDescription extends DataDescription implements Comparable { - public FieldDescription(String name, TypeDescription typeDescription) { - super(name, name, typeDescription); + private final TypeToken owningType; + + public FieldDescription(Field field, TypeToken owningType) { + super(ClassUtil.propertyNameOf(field), field, owningType.resolveType(field.getGenericType())); + + this.owningType = owningType; } @Override public int compareTo(FieldDescription other) { - return getName().compareTo(other.getName()); + return super.compareTo(other); } - + @Override - public String toString() { - return "FieldDescription[name=" + getName() + ", typeDescription=" + typeDescription + "]"; + public Field getOriginalMember() { + return (Field) super.getOriginalMember(); } @Override public boolean isPredicate() { - return typeDescription.isBoolean(); + return ClassUtil.isBoolean(valueType); } @Override public String getPredicate() { - final String retval = super.getNegativePredicate(); - return retval == null ? "is" + capitalize(originalMember) : originalMember; + final String retval = super.getNegativePredicate(); + return retval == null ? "is" + capitalize(originalMember.getName()) : originalMember.getName(); } @Override public String getNegativePredicate() { - final String retval = super.getNegativePredicate(); - return retval == null ? "isNot" + capitalize(originalMember) : retval; + final String retval = super.getNegativePredicate(); + return retval == null ? "isNot" + capitalize(originalMember.getName()) : retval; } + public TypeToken getOwningType() { + return owningType; + } } diff --git a/src/main/java/org/assertj/assertions/generator/description/GetterDescription.java b/src/main/java/org/assertj/assertions/generator/description/GetterDescription.java index 1e767d96..764d0be8 100644 --- a/src/main/java/org/assertj/assertions/generator/description/GetterDescription.java +++ b/src/main/java/org/assertj/assertions/generator/description/GetterDescription.java @@ -12,11 +12,13 @@ */ package org.assertj.assertions.generator.description; -import java.util.ArrayList; -import java.util.List; - +import com.google.common.collect.ImmutableList; +import com.google.common.reflect.Invokable; +import com.google.common.reflect.TypeToken; import org.assertj.assertions.generator.util.ClassUtil; +import java.lang.reflect.Method; + /** * Stores the information needed to generate an assertion for a getter method. *

@@ -30,7 +32,7 @@ * need to know : *

    *
  • the property name, here "age"
  • - *
  • property type
  • + *
  • property valueType
  • *
* Note that Person doesn't need to have an age field, just the getAge method. *

@@ -40,35 +42,36 @@ */ public class GetterDescription extends DataDescription implements Comparable { - private final List exceptions; + private final Invokable invokable; + private final ImmutableList> exceptions; - public GetterDescription(String propertyName, String origMethodName, TypeDescription typeDescription, - List exceptions) { - super(propertyName, origMethodName, typeDescription); - this.exceptions = new ArrayList(exceptions); - } + public GetterDescription(String propertyName, TypeToken owningType, Method method) { + super(propertyName, method, owningType.method(method).getReturnType()); - public String getPropertyName() { - return getName(); + this.invokable = owningType.method(method); + this.exceptions = invokable.getExceptionTypes(); } @Override - public int compareTo(GetterDescription other) { - return getOriginalMember().compareTo(other.getOriginalMember()); + public Method getOriginalMember() { + return (Method) super.getOriginalMember(); } @Override - public String toString() { - return "GetterDescription [propertyName=" + getName() + ", typeDescription=" + typeDescription + "]"; + public int compareTo(GetterDescription other) { + return super.compareTo(other); } - public List getExceptions() { + public ImmutableList> getExceptions() { return exceptions; } @Override public boolean isPredicate() { - return typeDescription.isBoolean() && ClassUtil.isValidPredicateName(originalMember); + return ClassUtil.isBoolean(valueType) && ClassUtil.isValidPredicateName(originalMember.getName()); } + public Invokable getInvokable() { + return invokable; + } } diff --git a/src/main/java/org/assertj/assertions/generator/description/TypeDescription.java b/src/main/java/org/assertj/assertions/generator/description/TypeDescription.java deleted file mode 100644 index 67186ae8..00000000 --- a/src/main/java/org/assertj/assertions/generator/description/TypeDescription.java +++ /dev/null @@ -1,129 +0,0 @@ -/** - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * Copyright 2012-2015 the original author or authors. - */ -package org.assertj.assertions.generator.description; - -/** - * Stores the information needed to generate an assertion for a field or a getter method, and data related to the field - * or getter returned type (mostly to import needed classes). - *

- * We need to know : - *

    - *
  • the type
  • - *
  • the involved generic types
  • - *
  • the component type in case of property is an array
  • - *
- *

- * For example, let's say we have the following method in class Team : - * - *

- * public List<Player> getPlayers()
- * 
- * - * To generate the following assertion : - * - *
- * TeamAssert hasPlayers(Player... expectedPlayers)
- * 
- * - * we need to know the generic type of players property : Player. - *

- * - * @author Joel Costigliola - * - */ -public class TypeDescription { - - private TypeName typeName; - private boolean isArray; - private boolean isIterable; - // for array or iterable types only - private TypeName elementTypeName; - - public TypeDescription(TypeName typeName) { - super(); - if (typeName == null) throw new IllegalArgumentException("typeName must not be null."); - this.typeName = typeName; - this.isArray = false; - this.isIterable = false; - this.elementTypeName = null; - } - - public String getSimpleNameWithOuterClass() { - return typeName.getSimpleNameWithOuterClass(); - } - - public boolean isArray() { - return isArray; - } - - public void setArray(boolean isArray) { - this.isArray = isArray; - } - - public boolean isPrimitive() { - return typeName.isPrimitive(); - } - - public boolean isRealNumber() { - return typeName.isRealNumber(); - } - - public boolean isWholeNumber() { - return typeName.isWholeNumber(); - } - - public boolean isBoolean() { - return typeName.isBoolean(); - } - - public boolean isChar() { - return typeName.isChar(); - } - - public boolean isPrimitiveWrapper() { - return typeName.isPrimitiveWrapper(); - } - - public TypeName getElementTypeName() { - return elementTypeName; - } - - public void setElementTypeName(TypeName elementTypeName) { - this.elementTypeName = elementTypeName; - } - - public boolean isIterable() { - return isIterable; - } - - public void setIterable(boolean isIterable) { - this.isIterable = isIterable; - } - - @Override - public String toString() { - return "TypeDescription[typeName=" + typeName + ", array=" + isArray + ", iterable=" + isIterable + ", primitive=" - + isPrimitive() + ", boolean=" + isBoolean() + ", elementTypeName=" + elementTypeName + "]"; - } - - public String getFullyQualifiedTypeNameIfNeeded(String packageName) { - return typeName.getFullyQualifiedTypeNameIfNeeded(packageName); - } - - public String getAssertTypeName(String packageName) { - if (typeName == null) { - return null; - } - return typeName.getAssertTypeName(packageName); - } -} diff --git a/src/main/java/org/assertj/assertions/generator/description/TypeName.java b/src/main/java/org/assertj/assertions/generator/description/TypeName.java deleted file mode 100644 index 4662c3cc..00000000 --- a/src/main/java/org/assertj/assertions/generator/description/TypeName.java +++ /dev/null @@ -1,235 +0,0 @@ -/** - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * Copyright 2012-2015 the original author or authors. - */ -package org.assertj.assertions.generator.description; - -import static com.google.common.base.Objects.equal; -import static org.apache.commons.lang3.ArrayUtils.contains; -import static org.apache.commons.lang3.StringUtils.indexOfAny; -import static org.apache.commons.lang3.StringUtils.isBlank; -import static org.apache.commons.lang3.StringUtils.isEmpty; -import static org.apache.commons.lang3.StringUtils.remove; -import static org.apache.commons.lang3.StringUtils.substringAfterLast; -import static org.apache.commons.lang3.StringUtils.substringBefore; - -import org.assertj.assertions.generator.util.ClassUtil; - -/** - * Describes a type with package and class/interface simple name. - *

- * {@link TypeName} is immutable. - */ -public class TypeName implements Comparable { - - private static final String CAPITAL_LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - private static final String BOOLEAN = "boolean"; - private static final String BOOLEAN_WRAPPER = "Boolean"; - private static final String CHAR = "char"; - private static final String CHARRACTER = "Character"; - private static final String NO_PACKAGE = ""; - public static final String JAVA_LANG_PACKAGE = "java.lang"; - protected static final String[] PRIMITIVE_TYPES = { "int", "long", "short", "byte", "float", "double", "char", BOOLEAN }; - protected static final String[] REAL_NUMBERS_TYPES = { "float", "double"}; - protected static final String[] REAL_NUMBERS_WRAPPER_TYPES = { "Float", "Double" }; - protected static final String[] WHOLE_NUMBERS_TYPES = { "int", "long", "short", "byte" }; - protected static final String[] WHOLE_NUMBERS_WRAPPER_TYPES = { "Integer", "Long", "Short", "Byte" }; - - private String typeSimpleName; - private String typeSimpleNameWithOuterClass; - private String typeSimpleNameWithOuterClassNotSeparatedByDots; - private String packageName; - - public TypeName(String typeSimpleName, String packageName) { - if (typeSimpleName == null) throw new IllegalArgumentException("type simple name should not be null"); - this.typeSimpleName = typeSimpleName; - this.typeSimpleNameWithOuterClass = typeSimpleName; - this.typeSimpleNameWithOuterClassNotSeparatedByDots = typeSimpleName; - setPackageName(packageName); - } - - /** - * WARNING : does not work for nested class like com.books.Author.Name, - * @param typeName - */ - public TypeName(String typeName) { - if (isBlank(typeName)) throw new IllegalArgumentException("type name should not be blank or null"); - int indexOfClassName = indexOfAny(typeName, CAPITAL_LETTERS); - if (indexOfClassName > 0) { - this.typeSimpleNameWithOuterClass = typeName.substring(indexOfClassName); - setPackageName(remove(typeName, "." + typeSimpleNameWithOuterClass)); - } else { - // primitive type => no package - this.typeSimpleNameWithOuterClass = typeName; - setPackageName(NO_PACKAGE); - } - this.typeSimpleName = typeSimpleNameWithOuterClass.contains(".") ? - substringAfterLast(typeSimpleNameWithOuterClass, ".") : typeSimpleNameWithOuterClass; - this.typeSimpleNameWithOuterClassNotSeparatedByDots = remove(typeSimpleNameWithOuterClass, "."); - } - - public TypeName(Class clazz) { - super(); - this.typeSimpleName = clazz.getSimpleName(); - this.typeSimpleNameWithOuterClass = ClassUtil.getSimpleNameWithOuterClass(clazz); - this.typeSimpleNameWithOuterClassNotSeparatedByDots = ClassUtil.getSimpleNameWithOuterClassNotSeparatedByDots(clazz); - this.packageName = clazz.getPackage() == null ? NO_PACKAGE : clazz.getPackage().getName(); - } - - public String getSimpleName() { - return typeSimpleName; - } - - public String getSimpleNameWithOuterClass() { - return typeSimpleNameWithOuterClass; - } - - public String getSimpleNameWithOuterClassNotSeparatedByDots() { - return typeSimpleNameWithOuterClassNotSeparatedByDots; - } - - public String getPackageName() { - return packageName; - } - - private void setPackageName(String packageName) { - this.packageName = packageName == null ? NO_PACKAGE : packageName; - } - - public boolean isPrimitive() { - return contains(PRIMITIVE_TYPES, typeSimpleName) && isEmpty(packageName); - } - - public boolean isRealNumber() { - return isPrimitiveRealNumber() || isRealNumberWrapper(); - } - - public boolean isWholeNumber() { - return isPrimitiveWholeNumber() || isWholeNumberWrapper(); - } - private boolean isPrimitiveRealNumber() { - return contains(REAL_NUMBERS_TYPES, typeSimpleName) && isEmpty(packageName); - } - - private boolean isRealNumberWrapper() { - return contains(REAL_NUMBERS_WRAPPER_TYPES, typeSimpleName) && JAVA_LANG_PACKAGE.equals(packageName); - } - - private boolean isPrimitiveWholeNumber() { - return contains(WHOLE_NUMBERS_TYPES, typeSimpleName) && isEmpty(packageName); - } - - private boolean isWholeNumberWrapper() { - return contains(WHOLE_NUMBERS_WRAPPER_TYPES, typeSimpleName) && JAVA_LANG_PACKAGE.equals(packageName); - } - - public boolean isBoolean() { - return isPrimitiveBoolean() || isBooleanWrapper(); - } - - private boolean isPrimitiveBoolean() { - return BOOLEAN.equals(typeSimpleName) && isEmpty(packageName); - } - - private boolean isBooleanWrapper() { - return BOOLEAN_WRAPPER.equals(typeSimpleName) && JAVA_LANG_PACKAGE.equals(packageName); - } - - public boolean isChar() { - return isPrimitiveChar() || isCharacter(); - } - - private boolean isCharacter() { - return CHARRACTER.equals(typeSimpleName) && JAVA_LANG_PACKAGE.equals(packageName); - } - - private boolean isPrimitiveChar() { - return CHAR.equals(typeSimpleName) && isEmpty(packageName); - } - - public boolean belongsToJavaLangPackage() { - return JAVA_LANG_PACKAGE.equals(packageName); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((packageName == null) ? 0 : packageName.hashCode()); - result = prime * result + ((typeSimpleName == null) ? 0 : typeSimpleName.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (getClass() != obj.getClass()) return false; - TypeName other = (TypeName) obj; - if (packageName == null) { - if (other.packageName != null) return false; - } else if (!packageName.equals(other.packageName)) return false; - if (typeSimpleName == null) { - if (other.typeSimpleName != null) return false; - } else if (!typeSimpleName.equals(other.typeSimpleName)) return false; - return true; - } - - @Override - public String toString() { - return getFullyQualifiedClassName(); - } - - @Override - public int compareTo(TypeName o) { - return getFullyQualifiedClassName().compareTo(o.getFullyQualifiedClassName()); - } - - public boolean isArray() { - return typeSimpleName.contains("[]"); - } - - public boolean isNested() { - return typeSimpleNameWithOuterClass.contains("."); - } - - public TypeName getOuterClassTypeName() { - if (!isNested()) return null; - return new TypeName(substringBefore(typeSimpleNameWithOuterClass, ".") , packageName); - } - - public String getFullyQualifiedClassName() { - return isEmpty(packageName) ? typeSimpleNameWithOuterClass : packageName + "." + typeSimpleNameWithOuterClass; - } - - public String getFullyQualifiedTypeNameIfNeeded(String targetPackage) { - return belongsToJavaLangPackage() || equal(targetPackage, packageName) ? getSimpleNameWithOuterClass() : getFullyQualifiedClassName(); - } - - public boolean isPrimitiveWrapper() { - return isWholeNumberWrapper() || isRealNumberWrapper() || isBooleanWrapper() || isCharacter(); - } - - // used to support navigation assertion https://github.com/joel-costigliola/assertj-assertions-generator/issues/67 - public String getAssertTypeName(String packageName) { - String fullName = getFullyQualifiedClassName(); - if (fullName.startsWith("java.")) { - // lets assume the name is an assertj wrapper - return "org.assertj.core.api." + getSimpleName() + "Assert"; - } else { - String prefix = fullName; - if (packageName != null && packageName.equals(getPackageName())) { - prefix = getSimpleName(); - } - return prefix + "Assert"; - } - } -} diff --git a/src/main/java/org/assertj/assertions/generator/description/converter/ClassDescriptionConverter.java b/src/main/java/org/assertj/assertions/generator/description/converter/ClassDescriptionConverter.java index 4c914858..d5349cea 100644 --- a/src/main/java/org/assertj/assertions/generator/description/converter/ClassDescriptionConverter.java +++ b/src/main/java/org/assertj/assertions/generator/description/converter/ClassDescriptionConverter.java @@ -18,7 +18,7 @@ * * General contract to convert an object to a {@link ClassDescription}. * - * @param the type to convert to {@link ClassDescription}. + * @param the valueType to convert to {@link ClassDescription}. * @author Joel Costigliola * */ diff --git a/src/main/java/org/assertj/assertions/generator/description/converter/ClassToClassDescriptionConverter.java b/src/main/java/org/assertj/assertions/generator/description/converter/ClassToClassDescriptionConverter.java index 32662247..7132aa60 100644 --- a/src/main/java/org/assertj/assertions/generator/description/converter/ClassToClassDescriptionConverter.java +++ b/src/main/java/org/assertj/assertions/generator/description/converter/ClassToClassDescriptionConverter.java @@ -12,34 +12,22 @@ */ package org.assertj.assertions.generator.description.converter; -import static org.apache.commons.lang3.StringUtils.remove; -import static org.assertj.assertions.generator.util.ClassUtil.declaredGetterMethodsOf; -import static org.assertj.assertions.generator.util.ClassUtil.declaredPublicFieldsOf; -import static org.assertj.assertions.generator.util.ClassUtil.getterMethodsOf; -import static org.assertj.assertions.generator.util.ClassUtil.inheritsCollectionOrIsIterable; -import static org.assertj.assertions.generator.util.ClassUtil.isArray; -import static org.assertj.assertions.generator.util.ClassUtil.nonStaticPublicFieldsOf; -import static org.assertj.assertions.generator.util.ClassUtil.propertyNameOf; +import com.google.common.reflect.TypeToken; +import org.assertj.assertions.generator.GenerateAssertion; +import org.assertj.assertions.generator.description.ClassDescription; +import org.assertj.assertions.generator.description.FieldDescription; +import org.assertj.assertions.generator.description.GetterDescription; import java.lang.reflect.Field; -import java.lang.reflect.GenericArrayType; -import java.lang.reflect.Member; import java.lang.reflect.Method; -import java.lang.reflect.ParameterizedType; -import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.TreeSet; -import org.assertj.assertions.generator.GenerateAssertion; -import org.assertj.assertions.generator.description.ClassDescription; -import org.assertj.assertions.generator.description.FieldDescription; -import org.assertj.assertions.generator.description.GetterDescription; -import org.assertj.assertions.generator.description.TypeDescription; -import org.assertj.assertions.generator.description.TypeName; -import org.assertj.assertions.generator.util.ClassUtil; +import static com.google.common.base.Preconditions.checkArgument; +import static org.assertj.assertions.generator.util.ClassUtil.*; -public class ClassToClassDescriptionConverter implements ClassDescriptionConverter> { +public class ClassToClassDescriptionConverter implements ClassDescriptionConverter> { private final AnnotationConfiguration annotationConfiguration; @@ -51,50 +39,56 @@ public ClassToClassDescriptionConverter(AnnotationConfiguration annotationConfig this.annotationConfiguration = annotationConfiguration; } - public ClassDescription convertToClassDescription(Class clazz) { - ClassDescription classDescription = new ClassDescription(new TypeName(clazz)); - classDescription.addGetterDescriptions(getterDescriptionsOf(clazz)); - classDescription.addFieldDescriptions(fieldDescriptionsOf(clazz)); - classDescription.addDeclaredGetterDescriptions(declaredGetterDescriptionsOf(clazz)); - classDescription.addDeclaredFieldDescriptions(declaredFieldDescriptionsOf(clazz)); - classDescription.setSuperType(clazz.getSuperclass()); + @Override + public ClassDescription convertToClassDescription(TypeToken type) { + checkArgument(!type.getRawType().isLocalClass(), "Can not support Local class %s", type); + ClassDescription classDescription = new ClassDescription(type); + classDescription.addGetterDescriptions(getterDescriptionsOf(type)); + classDescription.addFieldDescriptions(fieldDescriptionsOf(type)); + classDescription.addDeclaredGetterDescriptions(declaredGetterDescriptionsOf(type)); + classDescription.addDeclaredFieldDescriptions(declaredFieldDescriptionsOf(type)); + classDescription.setSuperType(type.getRawType().getSuperclass()); return classDescription; } - private Set getterDescriptionsOf(Class clazz) { - return doGetterDescriptionsOf(getterMethodsOf(clazz, annotationConfiguration.includedAnnotations()), clazz); + public ClassDescription convertToClassDescription(Class clazz) { + checkArgument(!clazz.isLocalClass(), "Can not support Local class %s", clazz); + return convertToClassDescription(TypeToken.of(clazz)); + } + + private Set getterDescriptionsOf(TypeToken type) { + return doGetterDescriptionsOf(getterMethodsOf(type, annotationConfiguration.includedAnnotations()), type); } - private Set declaredGetterDescriptionsOf(Class clazz) { - return doGetterDescriptionsOf(declaredGetterMethodsOf(clazz, annotationConfiguration.includedAnnotations()), clazz); + private Set declaredGetterDescriptionsOf(TypeToken type) { + return doGetterDescriptionsOf(declaredGetterMethodsOf(type, annotationConfiguration.includedAnnotations()), type); } - private Set doGetterDescriptionsOf(Set getters, Class clazz) { + private Set doGetterDescriptionsOf(Set getters, TypeToken type) { Set getterDescriptions = new TreeSet<>(); for (Method getter : getters) { // ignore getDeclaringClass if Enum - if (isGetDeclaringClassEnumGetter(getter, clazz)) continue; - final TypeDescription typeDescription = getTypeDescription(getter); - final List exceptionTypeNames = getExceptionTypeNames(getter); + if (isGetDeclaringClassEnumGetter(getter, type.getRawType())) continue; + String propertyName = propertyNameOf(getter); - getterDescriptions.add(new GetterDescription(propertyName, getter.getName(), typeDescription, - exceptionTypeNames)); + + getterDescriptions.add(new GetterDescription(propertyName, type, getter)); } return getterDescriptions; } - private Set declaredFieldDescriptionsOf(Class clazz) { - return doFieldDescriptionsOf(declaredPublicFieldsOf(clazz)); + private Set declaredFieldDescriptionsOf(TypeToken type) { + return doFieldDescriptionsOf(type, declaredPublicFieldsOf(type)); } - private Set fieldDescriptionsOf(Class clazz) { - return doFieldDescriptionsOf(nonStaticPublicFieldsOf(clazz)); + private Set fieldDescriptionsOf(TypeToken type) { + return doFieldDescriptionsOf(type, nonStaticPublicFieldsOf(type)); } - private Set doFieldDescriptionsOf(List fields) { + private Set doFieldDescriptionsOf(TypeToken type, List fields) { Set fieldDescriptions = new TreeSet<>(); for (Field field : fields) { - fieldDescriptions.add(new FieldDescription(field.getName(), getTypeDescription(field))); + fieldDescriptions.add(new FieldDescription(field, type)); } return fieldDescriptions; } @@ -103,72 +97,4 @@ private boolean isGetDeclaringClassEnumGetter(final Method getter, final Class getExceptionTypeNames(final Method getter) { - List exceptions = new ArrayList<>(); - for (Class exception : getter.getExceptionTypes()) { - exceptions.add(new TypeName(exception)); - } - return exceptions; - } - - private TypeDescription getTypeDescription(Member member) { - final Class type = getTypeOf(member); - if (isArray(type)) return buildArrayTypeDescription(type); - // we are interested in collections and iterable but not subtype of Iterable that are not collection. - // e.g. java.file.nio.Path that implements Iterable but has no ParameterizedType (ex : Path.getParent() -> Path) - if (inheritsCollectionOrIsIterable(type)) return buildIterableTypeDescription(member, type); - // "simple" type - return new TypeDescription(new TypeName(type)); - } - - private TypeDescription buildIterableTypeDescription(Member member, final Class type) { - final TypeDescription typeDescription = new TypeDescription(new TypeName(type)); - typeDescription.setIterable(true); - if (methodReturnTypeHasNoParameterInfo(member)) { - // not a ParameterizedType, i.e. no parameter information => use Object as element type. - typeDescription.setElementTypeName(new TypeName(Object.class)); - return typeDescription; - } - ParameterizedType parameterizedType = getParameterizedTypeOf(member); - if (parameterizedType.getActualTypeArguments()[0] instanceof GenericArrayType) { - GenericArrayType genericArrayType = (GenericArrayType) parameterizedType.getActualTypeArguments()[0]; - typeDescription.setElementTypeName(new TypeName(genericArrayType.toString())); - return typeDescription; - } - // Due to http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7151486, - // java 7 is not able to detect GenericArrayType correctly => let's use a different way to detect array - Class internalClass = ClassUtil.getClass(parameterizedType.getActualTypeArguments()[0]); - if (internalClass.isArray()) { - String componentTypeWithoutClassPrefix = remove(internalClass.getComponentType().toString(), "class "); - typeDescription.setElementTypeName(new TypeName(componentTypeWithoutClassPrefix + "[]")); - } else { - typeDescription.setElementTypeName(new TypeName(internalClass)); - } - return typeDescription; - } - - private static boolean methodReturnTypeHasNoParameterInfo(Member member) { - // java loose generic info if getter is overridden :( - return member instanceof Method && !(((Method) member).getGenericReturnType() instanceof ParameterizedType); - } - - private static Class getTypeOf(Member member) { - if (member instanceof Method) return ((Method) member).getReturnType(); - if (member instanceof Field) return ((Field) member).getType(); - throw new IllegalArgumentException("argument should be a Method or Field but was " + member.getClass()); - } - - private static ParameterizedType getParameterizedTypeOf(Member member) { - if (member instanceof Method) return (ParameterizedType) ((Method) member).getGenericReturnType(); - if (member instanceof Field) return (ParameterizedType) ((Field) member).getGenericType(); - throw new IllegalArgumentException("argument should be a Method or Field but was " + member.getClass()); - } - - private static TypeDescription buildArrayTypeDescription(final Class arrayType) { - final TypeDescription typeDescription = new TypeDescription(new TypeName(arrayType)); - typeDescription.setElementTypeName(new TypeName(arrayType.getComponentType())); - typeDescription.setArray(true); - return typeDescription; - } - } diff --git a/src/main/java/org/assertj/assertions/generator/util/ClassUtil.java b/src/main/java/org/assertj/assertions/generator/util/ClassUtil.java index 3939c58b..a293232d 100644 --- a/src/main/java/org/assertj/assertions/generator/util/ClassUtil.java +++ b/src/main/java/org/assertj/assertions/generator/util/ClassUtil.java @@ -12,55 +12,41 @@ */ package org.assertj.assertions.generator.util; -import static com.google.common.collect.Sets.newLinkedHashSet; -import static java.lang.reflect.Modifier.isPublic; -import static java.lang.reflect.Modifier.isStatic; -import static org.apache.commons.lang3.StringUtils.uncapitalize; +import com.google.common.base.Strings; +import com.google.common.collect.ImmutableSet; +import com.google.common.reflect.ClassPath; +import com.google.common.reflect.ClassPath.ClassInfo; +import com.google.common.reflect.TypeToken; +import org.apache.commons.lang3.ClassUtils; +import org.apache.commons.lang3.StringUtils; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.lang.annotation.Annotation; -import java.lang.reflect.Array; -import java.lang.reflect.Field; -import java.lang.reflect.GenericArrayType; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.lang.reflect.WildcardType; +import java.lang.reflect.*; import java.net.URL; import java.net.URLDecoder; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; +import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.apache.commons.lang3.ClassUtils; -import org.apache.commons.lang3.StringUtils; - -import com.google.common.collect.ImmutableSet; -import com.google.common.reflect.ClassPath; -import com.google.common.reflect.ClassPath.ClassInfo; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.collect.Sets.newLinkedHashSet; +import static java.lang.reflect.Modifier.isPublic; +import static java.lang.reflect.Modifier.isStatic; +import static org.apache.commons.lang3.StringUtils.remove; +import static org.apache.commons.lang3.StringUtils.uncapitalize; /** * Some utilities methods related to classes and packages. * * @author Joel Costigliola */ +@SuppressWarnings("WeakerAccess") public class ClassUtil { - public static final String IS_PREFIX = "is"; public static final String GET_PREFIX = "get"; private static final String CLASS_SUFFIX = ".class"; private static final Comparator GETTER_COMPARATOR = new Comparator() { @@ -69,12 +55,14 @@ public int compare(Method m1, Method m2) { return m1.getName().compareTo(m2.getName()); } }; + private static final Package JAVA_LANG_PACKAGE = Object.class.getPackage(); + private static final String CAPITAL_LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; /** * Call {@link #collectClasses(ClassLoader, String...)} with Thread.currentThread().getContextClassLoader() * */ - public static Set> collectClasses(String... classOrPackageNames) { + public static Set> collectClasses(String... classOrPackageNames) { return collectClasses(Thread.currentThread().getContextClassLoader(), classOrPackageNames); } @@ -90,10 +78,10 @@ public static Set> collectClasses(String... classOrPackageNames) { * @return the set of {@link Class}es found * @throws RuntimeException if any error occurs */ - public static Set> collectClasses(ClassLoader classLoader, String... classOrPackageNames) { - Set> classes = newLinkedHashSet(); + public static Set> collectClasses(ClassLoader classLoader, String... classOrPackageNames) { + Set> classes = newLinkedHashSet(); for (String classOrPackageName : classOrPackageNames) { - Class clazz = tryToLoadClass(classOrPackageName, classLoader); + TypeToken clazz = tryToLoadClass(classOrPackageName, classLoader); if (clazz != null) { classes.add(clazz); } else { @@ -112,12 +100,12 @@ public static Set> collectClasses(ClassLoader classLoader, String... cl * @return the list of Class found * @throws RuntimeException if any error occurs */ - private static Set> getClassesInPackage(String packageName, ClassLoader classLoader) { + private static Set> getClassesInPackage(String packageName, ClassLoader classLoader) { if (classLoader == null) { throw new IllegalArgumentException("Null class loader."); } // load classes from classpath file system, this won't load classes in jars - Set> packageClasses = getPackageClassesFromClasspathFiles(packageName, classLoader); + Set> packageClasses = getPackageClassesFromClasspathFiles(packageName, classLoader); // load classes from classpath jars try { packageClasses.addAll(getPackageClassesFromClasspathJars(packageName, classLoader)); @@ -127,16 +115,16 @@ private static Set> getClassesInPackage(String packageName, ClassLoader return packageClasses; } - private static Set> getPackageClassesFromClasspathJars(String packageName, ClassLoader classLoader) + private static Set> getPackageClassesFromClasspathJars(String packageName, ClassLoader classLoader) throws IOException { ImmutableSet classesInfo = ClassPath.from(classLoader).getTopLevelClassesRecursive(packageName); - Set> classesInPackage = new HashSet>(); + Set> classesInPackage = new HashSet<>(); for (ClassInfo classInfo : classesInfo) { - classesInPackage.add(classInfo.load()); + classesInPackage.add(TypeToken.of(classInfo.load())); } - Set> filteredClassesInPackage = new HashSet>(); - for (Class classFromJar : classesInPackage) { + Set> filteredClassesInPackage = new HashSet<>(); + for (TypeToken classFromJar : classesInPackage) { if (isClassCandidateToAssertionsGeneration(classFromJar)) { filteredClassesInPackage.add(classFromJar); } @@ -144,12 +132,12 @@ private static Set> getPackageClassesFromClasspathJars(String packageNa return filteredClassesInPackage; } - private static Set> getPackageClassesFromClasspathFiles(String packageName, ClassLoader classLoader) { + private static Set> getPackageClassesFromClasspathFiles(String packageName, ClassLoader classLoader) { try { String packagePath = packageName.replace('.', File.separatorChar); // Ask for all resources for the path Enumeration resources = classLoader.getResources(packagePath); - Set> classes = newLinkedHashSet(); + Set> classes = newLinkedHashSet(); while (resources.hasMoreElements()) { File directory = new File(URLDecoder.decode(resources.nextElement().getPath(), "UTF-8")); if (directory.canRead()) { @@ -172,15 +160,17 @@ private static Set> getPackageClassesFromClasspathFiles(String packageN * @param directory directory where to look for classes * @param packageName package name corresponding to directory * @param classLoader used classloader - * @return - * @throws UnsupportedEncodingException + * @return Set of all of the types in the directory + * @throws UnsupportedEncodingException thrown by {@link URLDecoder#decode(String, String)} */ - private static Set> getClassesInDirectory(File directory, String packageName, ClassLoader classLoader) + private static Set> getClassesInDirectory(File directory, String packageName, ClassLoader classLoader) throws UnsupportedEncodingException { - Set> classes = newLinkedHashSet(); + Set> classes = new LinkedHashSet<>(); + // Capture all the .class files in this directory // Get the list of the files contained in the package File[] files = directory.listFiles(); + checkNotNull(files, "No files were present in directory: %s", directory); for (File currentFile : files) { String currentFileName = currentFile.getName(); if (isClass(currentFileName)) { @@ -188,7 +178,7 @@ private static Set> getClassesInDirectory(File directory, String packag try { // removes the .class extension String className = packageName + '.' + StringUtils.remove(currentFileName, CLASS_SUFFIX); - Class loadedClass = loadClass(className, classLoader); + TypeToken loadedClass = loadClass(className, classLoader); // we are only interested in public classes that are neither anonymous nor local if (isClassCandidateToAssertionsGeneration(loadedClass)) { classes.add(loadedClass); @@ -201,9 +191,11 @@ private static Set> getClassesInDirectory(File directory, String packag // It's another package String subPackageName = packageName + ClassUtils.PACKAGE_SEPARATOR + currentFileName; // Ask for all resources for the path - URL resource = classLoader.getResource(subPackageName.replace('.', File.separatorChar)); + String path = subPackageName.replace('.', File.separatorChar); + URL resource = classLoader.getResource(path); + checkNotNull(resource, "resource URL from package is null, package %s", path); File subDirectory = new File(URLDecoder.decode(resource.getPath(), "UTF-8")); - Set> classesForSubPackage = getClassesInDirectory(subDirectory, subPackageName, classLoader); + Set> classesForSubPackage = getClassesInDirectory(subDirectory, subPackageName, classLoader); classes.addAll(classesForSubPackage); } } @@ -214,16 +206,20 @@ private static Set> getClassesInDirectory(File directory, String packag * @param loadedClass * @return */ - private static boolean isClassCandidateToAssertionsGeneration(Class loadedClass) { - return loadedClass != null && isPublic(loadedClass.getModifiers()) && !loadedClass.isAnonymousClass() - && !loadedClass.isLocalClass(); + private static boolean isClassCandidateToAssertionsGeneration(TypeToken loadedClass) { + if (loadedClass == null) { + return false; + } + + Class raw = loadedClass.getRawType(); + return isPublic(raw.getModifiers()) && !raw.isAnonymousClass() && !raw.isLocalClass(); } private static boolean isClass(String fileName) { return fileName.endsWith(CLASS_SUFFIX); } - private static Class tryToLoadClass(String className, ClassLoader classLoader) { + private static TypeToken tryToLoadClass(String className, ClassLoader classLoader) { try { return loadClass(className, classLoader); } catch (ClassNotFoundException e) { @@ -231,8 +227,8 @@ private static Class tryToLoadClass(String className, ClassLoader classLoader } } - private static Class loadClass(String className, ClassLoader classLoader) throws ClassNotFoundException { - return Class.forName(className, false, classLoader); + private static TypeToken loadClass(String className, ClassLoader classLoader) throws ClassNotFoundException { + return TypeToken.of(Class.forName(className, false, classLoader)); } /** @@ -248,18 +244,20 @@ private static Class loadClass(String className, ClassLoader classLoader) thr * isMostValuablePlayer -> mostValuablePlayer * * - * @param getter getter method to deduce property from. + * @param member getter method to deduce property from. * @return the property name of given getter method */ - public static String propertyNameOf(Method getter) { - String methodName = getter.getName(); - String prefixToRemove = isPredicate(getter) ? IS_PREFIX : GET_PREFIX; - int pos = methodName.indexOf(prefixToRemove); + public static String propertyNameOf(Member member) { + String memberName = member.getName(); + String predicatePrefix = getPredicatePrefix(memberName); + String prefixToRemove = predicatePrefix != null ? predicatePrefix : GET_PREFIX; + + int pos = memberName.indexOf(prefixToRemove); if (pos != StringUtils.INDEX_NOT_FOUND) { - String propertyWithCapitalLetter = methodName.substring(pos + prefixToRemove.length()); + String propertyWithCapitalLetter = memberName.substring(pos + prefixToRemove.length()); return uncapitalize(propertyWithCapitalLetter); } else { - return methodName; + return memberName; } } @@ -267,10 +265,6 @@ public static boolean inheritsCollectionOrIsIterable(Class returnType) { return Collection.class.isAssignableFrom(returnType) || Iterable.class.equals(returnType); } - public static boolean isArray(Class returnType) { - return returnType.isArray(); - } - public static boolean isStandardGetter(Method method) { return isValidStandardGetterName(method.getName()) && !Void.TYPE.equals(method.getReturnType()) @@ -308,7 +302,7 @@ public static boolean isValidGetterName(String methodName) { static private final Pattern PREFIX_PATTERN; - static private final Map PREDICATE_PREFIXES; + static public final Map PREDICATE_PREFIXES; static private final Comparator LONGEST_TO_SHORTEST = new Comparator() { @Override @@ -323,17 +317,20 @@ public int compare(String o1, String o2) { { "is", "isNot" }, { "was", "wasNot" }, { "can", "cannot" }, + { "canBe", "cannotBe" }, { "should", "shouldNot" }, + { "shouldBe", "shouldNotBe" }, { "has", "doesNotHave" }, + { "willBe", "willNotBe" }, { "will", "willNot" }, }; StringBuilder pattern = new StringBuilder("^(?:get"); - Map map = new HashMap(); + Map map = new HashMap<>(); for (String[] pair : predicates) { map.put(pair[0], pair[1]); map.put(pair[1], pair[0]); } - TreeSet sort = new TreeSet(LONGEST_TO_SHORTEST); + TreeSet sort = new TreeSet<>(LONGEST_TO_SHORTEST); sort.addAll(map.keySet()); for (String prefix : sort) { pattern.append('|').append(prefix); @@ -367,21 +364,22 @@ public static String getNegativePredicateFor(String name) { return null; } - public static Set declaredGetterMethodsOf(Class clazz, Set> includeAnnotations) { + public static Set declaredGetterMethodsOf(TypeToken type, Set> includeAnnotations) { + Class clazz = type.getRawType(); boolean isClassAnnotated = containsAny(clazz.getDeclaredAnnotations(), includeAnnotations); return filterGetterMethods(clazz.getDeclaredMethods(), includeAnnotations, isClassAnnotated); } - public static Set getterMethodsOf(Class clazz, Set> includeAnnotations) { + public static Set getterMethodsOf(TypeToken type, Set> includeAnnotations) { + Class clazz = type.getRawType(); boolean isClassAnnotated = containsAny(clazz.getDeclaredAnnotations(), includeAnnotations); return filterGetterMethods(clazz.getMethods(), includeAnnotations, isClassAnnotated); } private static Set filterGetterMethods(Method[] methods, Set> includeAnnotations, boolean isClassAnnotated) { - Set getters = new TreeSet(GETTER_COMPARATOR); - for (int i = 0; i < methods.length; i++) { - Method method = methods[i]; + Set getters = new TreeSet<>(GETTER_COMPARATOR); + for (Method method : methods) { if (isPublic(method.getModifiers()) && isNotDefinedInObjectClass(method) && isGetter(method, includeAnnotations, isClassAnnotated)) { @@ -397,9 +395,9 @@ private static boolean isGetter(Method method, Set> includeAnnotations, || isAnnotated(method, includeAnnotations, isClassAnnotated); } - public static List nonStaticPublicFieldsOf(Class clazz) { - Field[] fields = clazz.getFields(); - List nonStaticPublicFields = new ArrayList(); + public static List nonStaticPublicFieldsOf(TypeToken type) { + Field[] fields = type.getRawType().getFields(); + List nonStaticPublicFields = new ArrayList<>(); for (Field field : fields) { if (isNotStaticPublicField(field)) { nonStaticPublicFields.add(field); @@ -408,9 +406,9 @@ public static List nonStaticPublicFieldsOf(Class clazz) { return nonStaticPublicFields; } - public static List declaredPublicFieldsOf(Class clazz) { - Field[] fields = clazz.getDeclaredFields(); - List nonStaticPublicFields = new ArrayList(); + public static List declaredPublicFieldsOf(TypeToken type) { + Field[] fields = type.getRawType().getDeclaredFields(); + List nonStaticPublicFields = new ArrayList<>(); for (Field field : fields) { if (isNotStaticPublicField(field)) { nonStaticPublicFields.add(field); @@ -429,15 +427,15 @@ private static boolean isNotDefinedInObjectClass(Method method) { } public static Set> getClassesRelatedTo(Type type) { - Set> classes = new HashSet>(); + Set> classes = new HashSet<>(); - // non generic type : just add current type. + // non generic valueType : just add current valueType. if (type instanceof Class) { classes.add((Class) type); return classes; } - // generic type : add current type and its parameter types + // generic valueType : add current valueType and its parameter types if (type instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) type; for (Type actualTypeArgument : parameterizedType.getActualTypeArguments()) { @@ -468,8 +466,7 @@ public static String getSimpleNameWithOuterClass(Class clazz) { if (isNotNestedClass(clazz)) { return clazz.getSimpleName(); } - String nestedClassName = null; - nestedClassName = clazz.getName(); + String nestedClassName = clazz.getName(); nestedClassName = nestedClassName.substring(clazz.getPackage().getName().length() + 1); nestedClassName = nestedClassName.replace('$', '.'); return nestedClassName; @@ -492,8 +489,7 @@ public static String getSimpleNameWithOuterClassNotSeparatedByDots(Class claz if (isNotNestedClass(clazz)) { return clazz.getSimpleName(); } - String nestedClassName = null; - nestedClassName = clazz.getName(); + String nestedClassName = clazz.getName(); nestedClassName = nestedClassName.substring(clazz.getPackage().getName().length() + 1); nestedClassName = StringUtils.remove(nestedClassName, '$'); return nestedClassName; @@ -504,9 +500,9 @@ private static boolean isNotNestedClass(Class clazz) { } /** - * Get the underlying class for a type, or null if the type is a variable type. + * Get the underlying class for a valueType, or null if the valueType is a variable valueType. * - * @param type the type + * @param type the valueType * @return the underlying class */ public static Class getClass(final Type type) { @@ -529,4 +525,285 @@ public static Class getClass(final Type type) { return null; } + /** + * Checks if the package, {@code child} is under the package {@code parent}. + * @param child Child package + * @param parent Parent package + * @return True iff the child package is under the parent, false if not or either is {@code null}. + * + * @see #isInnerPackageOf(String, String) String argument equivalent + */ + public static boolean isInnerPackageOf(Package child, Package parent) { + return child != null && parent != null + && child.getName().startsWith(parent.getName()); + } + + /** + * Utility version that allows to pass a string and {@link Package}. + *
+ * Delegates to {@link #isInnerPackageOf(String, String)}. + * + * @see #isInnerPackageOf(String, String) + */ + public static boolean isInnerPackageOf(Package child, String parent) { + return child != null && isInnerPackageOf(child.getName(), parent); + } + + /** + * Checks if the package, {@code child} is under the package {@code parent}. + * @param parentPackage Parent package + * @param childPackage Child package + * @return True iff the child package is under the parent, false if not or either is {@code null}. + * + * @see #isInnerPackageOf(String, String) String argument equivalent + */ + public static boolean isInnerPackageOf(String childPackage, String parentPackage) { + checkArgument(!Strings.isNullOrEmpty(childPackage), "childPackage is null or empty"); + checkNotNull(parentPackage, "parentPackage is null or empty"); + + return childPackage.startsWith(parentPackage); + } + + /** + * Checks if the type passed is a member of {@code java.lang} or is a "built-in" type (e.g. primitive or array). + * @return true if part of java language + */ + public static boolean isJavaLangType(TypeToken type) { + return type.isPrimitive() || type.isArray() || Objects.equals(JAVA_LANG_PACKAGE, type.getRawType().getPackage()); + } + + /** + * Checks if the type passed is a member of {@code java.lang} or is a "built-in" type (e.g. primitive or array). + * @return true if part of java language + * + * @see #isJavaLangType(TypeToken) + */ + public static boolean isJavaLangType(Type type) { + return isJavaLangType(TypeToken.of(type)); + } + + /** + * Generates a "type declaration" that could be used in Java code based on the {@code type} and if it is a parameter, + * it will try to be as "flexible" as possible. + * + * @param type Type to get declaration for + * @param asParameter True if the type is being used as a parameter + * @return String representation of the type + * + * @see #getTypeDeclaration(TypeToken, boolean, boolean) + */ + public static String getTypeDeclaration(TypeToken type, final boolean asParameter, boolean fullyQualified) { + StringBuilder bld = new StringBuilder(); + Class raw = type.getRawType(); + getTypeDeclaration(bld, (raw.getPackage() == null ? null : raw.getPackage().getName()), type, asParameter, fullyQualified); + return bld.toString(); + } + + /** + * Uses the package name as a "local package" and tries to discern whether or not to generate + * fully qualified names. + * @param type Type to get declaration for + * @param packageName local package name + * @param asParameter True if the type is being used as a parameter + * @return String representation of the type + * + * @see #getTypeDeclaration(TypeToken, boolean, boolean) + */ + public static String getTypeDeclarationWithinPackage(TypeToken type, String packageName, final boolean asParameter) { + + boolean reqFQN = !Objects.equals(packageName, JAVA_LANG_PACKAGE.getName()) + && (!type.isPrimitive() && !type.isArray() && !Objects.equals(packageName, type.getRawType().getPackage().getName())); + StringBuilder bld = new StringBuilder(); + getTypeDeclaration(bld, packageName, type, asParameter, reqFQN); + return bld.toString(); + } + + /** + * helper method for {@code #getTypeDeclarationXXX()} + * @see #getTypeDeclaration(TypeToken, boolean, boolean) + * @see #getTypeDeclarationWithinPackage(TypeToken, String, boolean) + */ + private static void getTypeDeclaration(StringBuilder bld, String basePackage, TypeToken type, boolean asParameter, boolean fullyQualified) { + + Class raw = type.getRawType(); + + // Gotta do some special casing + if (type.isArray()) { + getTypeDeclaration(bld, basePackage, type.getComponentType(), asParameter, fullyQualified); + bld.append("[]"); + } else if (type.isPrimitive()) { + bld.append(raw.toString()); + } else { + // Now we have some types that could be generic, so we have to do more + // to serialize it to the declaration + + if (raw.isMemberClass()) { // inner class + TypeToken outerClass = type.resolveType(raw.getEnclosingClass()); + getTypeDeclaration(bld, basePackage, outerClass, asParameter, fullyQualified); + bld.append("."); + + } else { + // it's a normal class, so just append the package here if needed + if (fullyQualified && !isJavaLangType(type)) { + bld.append(type.getRawType().getPackage().getName()); + bld.append("."); + } + } + + bld.append(raw.getSimpleName()); + + // Now handle generics + if (raw.getTypeParameters().length > 0) { + bld.append("<"); + boolean first = true; + for (TypeVariable tv : raw.getTypeParameters()) { + // only append at the end + if (!first) { + bld.append(','); + } + first = false; + + TypeToken paramType = type.resolveType(tv); + Class rawParam = paramType.getRawType(); + String typeString = StringUtils.removeAll(paramType.toString(), "capture#\\d+-of\\s+"); + typeString = typeString.replace("(\\?\\s+extends\\s+){2,}", "? extends "); + + boolean isWildCard = typeString.contains("?"); + + // Some specializations need to be done to make sure that the arguments + // are property pulled out and written + + // If its a wild card and it has no boundary other than Object, + // we just use the wild card + if (isWildCard && rawParam.equals(Object.class)) { + bld.append("?"); + continue; + } + + if (asParameter) { + // We handle parameters differently so that it's accepted more "flexibility" + bld.append("? extends "); + } + + // now we recursively add the type parameter, we set `asParameter` to false + // because odds are it will become wrong to keep adding the "extends" boundaries + Package paramPackage = paramType.getRawType().getPackage(); + + getTypeDeclaration(bld, basePackage, paramType, false, + fullyQualified + || ((paramPackage != null && !Objects.equals(basePackage, paramPackage.getName())) + && Objects.equals(paramPackage, raw.getPackage()))); + } + + bld.append(">"); + } + } + + } + + /** + * Gets the name of the class that will be the "assert". + * @param type Type being tested + * @param packageName package this type will reside in + * @return Name for "assert" type + */ + // used to support navigation assertion + // https://github.com/joel-costigliola/assertj-assertions-generator/issues/67 + public static String getAssertType(TypeToken type, String packageName) { + + TypeToken wrapped = type.wrap(); + Class raw = wrapped.getRawType(); + + String typeName = null; + if (isJavaLangType(wrapped)) { + try { + String builtInName = "org.assertj.core.api." + raw.getSimpleName() + "Assert"; + // try to get the class, if it exists, then we know its valid + Class.forName(builtInName); + + typeName = builtInName.substring(0, builtInName.length() - "Assert".length()); + } catch (ClassNotFoundException cfne) { + // it wasn't found, this means the class doesn't exist, so fall through + } + } + + if (typeName == null) { + typeName = type.getRawType().getName(); + } + + return resolveTypeNameInPackage(typeName + "Assert", packageName); + } + + /** + * Gets the name of a type without the package if {@code currentPackage} is the same as + * {@link Class#getPackage() type's package}. + * + * @param type Type to import + * @param currentPackage package context for the string + * @return String Name resolved within the package + */ + public static String resolveTypeNameInPackage(TypeToken type, String currentPackage) { + // we special case java.lang types because they never need a FQN. + if (isJavaLangType(type)) { + return type.getRawType().getSimpleName(); + } + + return resolveTypeNameInPackage(type.getRawType().getName(), currentPackage); + } + + /** + * Gets the name of a type without the package if {@code currentPackage} is the same as + * {@link Class#getPackage() type's package}. + * + * @param type Type to import + * @param currentPackage package context for the string + * @return String Name resolved within the package + */ + public static String resolveTypeNameInPackage(Type type, String currentPackage) { + return resolveTypeNameInPackage(TypeToken.of(type), currentPackage); + } + + /** + * Gets the name of a type without the package if {@code currentPackage} is the same as + * {@link Class#getPackage() type's package}. + * + * @param type Type to import + * @param currentPackage package context for the string + * @return Name resolved within the package + */ + private static String resolveTypeNameInPackage(String type, String currentPackage) { + if (!Strings.isNullOrEmpty(currentPackage) && type.startsWith(currentPackage)) { + return type.substring(currentPackage.length() + 1, type.length()); + } else { + return type; + } + } + + /** + * Gets a type name without any dots in it if they are present -- this is for nested classes + * @param typeName String name of the type + * @return Type without any {@code '.'} characters + */ + public static String getTypeNameWithoutDots(String typeName) { + int indexOfClassName = StringUtils.indexOfAny(typeName, CAPITAL_LETTERS); + final String typeSimpleNameWithOuterClass; + if (indexOfClassName > 0) { + typeSimpleNameWithOuterClass = typeName.substring(indexOfClassName); + } else { + // primitive valueType => no package + typeSimpleNameWithOuterClass = typeName; + } + + return remove(typeSimpleNameWithOuterClass, "."); + } + + /** + * Checks if a type is a boolean type + * @param type Type to check + * @return true iff the type is a boolean. + */ + public static boolean isBoolean(TypeToken type) { + TypeToken unwrapped = type.unwrap(); + return unwrapped.isSubtypeOf(boolean.class); + } } diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml index 7b4df334..93c2bd4b 100644 --- a/src/main/resources/logback.xml +++ b/src/main/resources/logback.xml @@ -1,7 +1,7 @@ - %d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n diff --git a/src/main/resources/templates/custom_hierarchical_assertion_class_template.txt b/src/main/resources/templates/custom_hierarchical_assertion_class_template.txt index a3860267..fe736afe 100644 --- a/src/main/resources/templates/custom_hierarchical_assertion_class_template.txt +++ b/src/main/resources/templates/custom_hierarchical_assertion_class_template.txt @@ -1,6 +1,5 @@ package ${package}; - /** * {@link ${class_to_assert}} specific assertions - Generated by CustomAssertionGenerator. * diff --git a/src/main/resources/templates/has_assertion_template.txt b/src/main/resources/templates/has_assertion_template.txt index 355eee5f..500f51de 100644 --- a/src/main/resources/templates/has_assertion_template.txt +++ b/src/main/resources/templates/has_assertion_template.txt @@ -5,13 +5,13 @@ * @return this assertion object. * @throws AssertionError - if the actual ${class_to_assert}'s ${property} is not equal to the given one.${throws_javadoc} */ - public ${self_type} has${Property}(${propertyType} ${property_safe}) ${throws}{ + public ${self_type} has${Property}(${propertyType_parameter} ${property_safe}) ${throws}{ // check that actual ${class_to_assert} we want to make assertions on is not null. isNotNull(); // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting ${property} of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - + // null safe check ${propertyType} actual${Property} = actual.${getter}(); if (!Objects.areEqual(actual${Property}, ${property_safe})) { diff --git a/src/main/resources/templates/has_assertion_template_for_char.txt b/src/main/resources/templates/has_assertion_template_for_char.txt index d5dd842e..b177edf0 100644 --- a/src/main/resources/templates/has_assertion_template_for_char.txt +++ b/src/main/resources/templates/has_assertion_template_for_char.txt @@ -5,14 +5,14 @@ * @return this assertion object. * @throws AssertionError - if the actual ${class_to_assert}'s ${property} is not equal to the given one.${throws_javadoc} */ - public ${self_type} has${Property}(${propertyType} ${property_safe}) ${throws}{ + public ${self_type} has${Property}(${propertyType_parameter} ${property_safe}) ${throws}{ // check that actual ${class_to_assert} we want to make assertions on is not null. isNotNull(); // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting ${property} of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - - // check + + // check ${property} char matches ${propertyType} actual${Property} = actual.${getter}(); if (actual${Property} != ${property_safe}) { failWithMessage(assertjErrorMessage, actual, ${property_safe}, actual${Property}); diff --git a/src/main/resources/templates/has_assertion_template_for_character.txt b/src/main/resources/templates/has_assertion_template_for_character.txt index 355eee5f..500f51de 100644 --- a/src/main/resources/templates/has_assertion_template_for_character.txt +++ b/src/main/resources/templates/has_assertion_template_for_character.txt @@ -5,13 +5,13 @@ * @return this assertion object. * @throws AssertionError - if the actual ${class_to_assert}'s ${property} is not equal to the given one.${throws_javadoc} */ - public ${self_type} has${Property}(${propertyType} ${property_safe}) ${throws}{ + public ${self_type} has${Property}(${propertyType_parameter} ${property_safe}) ${throws}{ // check that actual ${class_to_assert} we want to make assertions on is not null. isNotNull(); // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting ${property} of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - + // null safe check ${propertyType} actual${Property} = actual.${getter}(); if (!Objects.areEqual(actual${Property}, ${property_safe})) { diff --git a/src/main/resources/templates/has_assertion_template_for_primitive.txt b/src/main/resources/templates/has_assertion_template_for_primitive.txt index d5dd842e..9dd31d3a 100644 --- a/src/main/resources/templates/has_assertion_template_for_primitive.txt +++ b/src/main/resources/templates/has_assertion_template_for_primitive.txt @@ -5,13 +5,13 @@ * @return this assertion object. * @throws AssertionError - if the actual ${class_to_assert}'s ${property} is not equal to the given one.${throws_javadoc} */ - public ${self_type} has${Property}(${propertyType} ${property_safe}) ${throws}{ + public ${self_type} has${Property}(${propertyType_parameter} ${property_safe}) ${throws}{ // check that actual ${class_to_assert} we want to make assertions on is not null. isNotNull(); // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting ${property} of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - + // check ${propertyType} actual${Property} = actual.${getter}(); if (actual${Property} != ${property_safe}) { diff --git a/src/main/resources/templates/has_assertion_template_for_primitive_wrapper.txt b/src/main/resources/templates/has_assertion_template_for_primitive_wrapper.txt index 355eee5f..500f51de 100644 --- a/src/main/resources/templates/has_assertion_template_for_primitive_wrapper.txt +++ b/src/main/resources/templates/has_assertion_template_for_primitive_wrapper.txt @@ -5,13 +5,13 @@ * @return this assertion object. * @throws AssertionError - if the actual ${class_to_assert}'s ${property} is not equal to the given one.${throws_javadoc} */ - public ${self_type} has${Property}(${propertyType} ${property_safe}) ${throws}{ + public ${self_type} has${Property}(${propertyType_parameter} ${property_safe}) ${throws}{ // check that actual ${class_to_assert} we want to make assertions on is not null. isNotNull(); // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting ${property} of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - + // null safe check ${propertyType} actual${Property} = actual.${getter}(); if (!Objects.areEqual(actual${Property}, ${property_safe})) { diff --git a/src/main/resources/templates/has_assertion_template_for_real_number.txt b/src/main/resources/templates/has_assertion_template_for_real_number.txt index 7532dcfb..172e98ac 100644 --- a/src/main/resources/templates/has_assertion_template_for_real_number.txt +++ b/src/main/resources/templates/has_assertion_template_for_real_number.txt @@ -5,14 +5,14 @@ * @return this assertion object. * @throws AssertionError - if the actual ${class_to_assert}'s ${property} is not equal to the given one.${throws_javadoc} */ - public ${self_type} has${Property}(${propertyType} ${property_safe}) ${throws}{ + public ${self_type} has${Property}(${propertyType_parameter} ${property_safe}) ${throws}{ // check that actual ${class_to_assert} we want to make assertions on is not null. isNotNull(); // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting ${property} of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - // check + // check value for ${property} ${propertyType} actual${Property} = actual.${getter}(); if (actual${Property} != ${property_safe}) { failWithMessage(assertjErrorMessage, actual, ${property_safe}, actual${Property}); @@ -31,16 +31,16 @@ * @return this assertion object. * @throws AssertionError - if the actual ${class_to_assert}'s ${property} is not close enough to the given value.${throws_javadoc} */ - public ${self_type} has${Property}CloseTo(${propertyType} ${property_safe}, ${propertyType} offset) ${throws}{ + public ${self_type} has${Property}CloseTo(${propertyType_parameter} ${property_safe}, ${propertyType} offset) ${throws}{ // check that actual ${class_to_assert} we want to make assertions on is not null. isNotNull(); ${propertyType} actual${Property} = actual.${getter}(); - + // overrides the default error message with a more explicit one String assertjErrorMessage = String.format("\nExpecting ${property}:\n <%s>\nto be close to:\n <%s>\nby less than <%s> but difference was <%s>", actual${Property}, ${property_safe}, offset, Math.abs(${property_safe} - actual${Property})); - + // check Assertions.assertThat(actual${Property}).overridingErrorMessage(assertjErrorMessage).isCloseTo(${property_safe}, Assertions.within(offset)); diff --git a/src/main/resources/templates/has_assertion_template_for_real_number_wrapper.txt b/src/main/resources/templates/has_assertion_template_for_real_number_wrapper.txt index 49a85a3d..2d5b0b75 100644 --- a/src/main/resources/templates/has_assertion_template_for_real_number_wrapper.txt +++ b/src/main/resources/templates/has_assertion_template_for_real_number_wrapper.txt @@ -5,7 +5,7 @@ * @return this assertion object. * @throws AssertionError - if the actual ${class_to_assert}'s ${property} is not equal to the given one.${throws_javadoc} */ - public ${self_type} has${Property}(${propertyType} ${property_safe}) ${throws}{ + public ${self_type} has${Property}(${propertyType_parameter} ${property_safe}) ${throws}{ // check that actual ${class_to_assert} we want to make assertions on is not null. isNotNull(); @@ -31,16 +31,16 @@ * @return this assertion object. * @throws AssertionError - if the actual ${class_to_assert}'s ${property} is not close enough to the given value.${throws_javadoc} */ - public ${self_type} has${Property}CloseTo(${propertyType} ${property_safe}, ${propertyType} offset) ${throws}{ + public ${self_type} has${Property}CloseTo(${propertyType_parameter} ${property_safe}, ${propertyType} offset) ${throws}{ // check that actual ${class_to_assert} we want to make assertions on is not null. isNotNull(); ${propertyType} actual${Property} = actual.${getter}(); - + // overrides the default error message with a more explicit one String assertjErrorMessage = String.format("\nExpecting ${property}:\n <%s>\nto be close to:\n <%s>\nby less than <%s> but difference was <%s>", actual${Property}, ${property_safe}, offset, Math.abs(${property_safe} - actual${Property})); - + // check Assertions.assertThat(actual${Property}).overridingErrorMessage(assertjErrorMessage).isCloseTo(${property_safe}, Assertions.within(offset)); diff --git a/src/main/resources/templates/has_assertion_template_for_whole_number.txt b/src/main/resources/templates/has_assertion_template_for_whole_number.txt index d5dd842e..9dd31d3a 100644 --- a/src/main/resources/templates/has_assertion_template_for_whole_number.txt +++ b/src/main/resources/templates/has_assertion_template_for_whole_number.txt @@ -5,13 +5,13 @@ * @return this assertion object. * @throws AssertionError - if the actual ${class_to_assert}'s ${property} is not equal to the given one.${throws_javadoc} */ - public ${self_type} has${Property}(${propertyType} ${property_safe}) ${throws}{ + public ${self_type} has${Property}(${propertyType_parameter} ${property_safe}) ${throws}{ // check that actual ${class_to_assert} we want to make assertions on is not null. isNotNull(); // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting ${property} of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - + // check ${propertyType} actual${Property} = actual.${getter}(); if (actual${Property} != ${property_safe}) { diff --git a/src/main/resources/templates/has_assertion_template_for_whole_number_wrapper.txt b/src/main/resources/templates/has_assertion_template_for_whole_number_wrapper.txt index 355eee5f..500f51de 100644 --- a/src/main/resources/templates/has_assertion_template_for_whole_number_wrapper.txt +++ b/src/main/resources/templates/has_assertion_template_for_whole_number_wrapper.txt @@ -5,13 +5,13 @@ * @return this assertion object. * @throws AssertionError - if the actual ${class_to_assert}'s ${property} is not equal to the given one.${throws_javadoc} */ - public ${self_type} has${Property}(${propertyType} ${property_safe}) ${throws}{ + public ${self_type} has${Property}(${propertyType_parameter} ${property_safe}) ${throws}{ // check that actual ${class_to_assert} we want to make assertions on is not null. isNotNull(); // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting ${property} of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - + // null safe check ${propertyType} actual${Property} = actual.${getter}(); if (!Objects.areEqual(actual${Property}, ${property_safe})) { diff --git a/src/main/resources/templates/has_elements_assertion_template_for_array.txt b/src/main/resources/templates/has_elements_assertion_template_for_array.txt index f114557b..58826935 100644 --- a/src/main/resources/templates/has_elements_assertion_template_for_array.txt +++ b/src/main/resources/templates/has_elements_assertion_template_for_array.txt @@ -11,7 +11,7 @@ // check that given ${elementType} varargs is not null. if (${property_safe} == null) failWithMessage("Expecting ${property} parameter not to be null."); - + // check with standard error message (use overridingErrorMessage before contains to set your own message). Assertions.assertThat(actual.${getter}()).contains(${property_safe}); @@ -21,7 +21,7 @@ /** * Verifies that the actual ${class_to_assert}'s ${property} contains only the given ${elementType} elements and nothing else in whatever order. - * + * * @param ${property_safe} the given elements that should be contained in actual ${class_to_assert}'s ${property}. * @return this assertion object. * @throws AssertionError if the actual ${class_to_assert}'s ${property} does not contain all given ${elementType} elements and nothing else.${throws_javadoc} @@ -32,7 +32,7 @@ // check that given ${elementType} varargs is not null. if (${property_safe} == null) failWithMessage("Expecting ${property} parameter not to be null."); - + // check with standard error message (use overridingErrorMessage before contains to set your own message). Assertions.assertThat(actual.${getter}()).containsOnly(${property_safe}); @@ -53,7 +53,7 @@ // check that given ${elementType} varargs is not null. if (${property_safe} == null) failWithMessage("Expecting ${property} parameter not to be null."); - + // check with standard error message (use overridingErrorMessage before contains to set your own message). Assertions.assertThat(actual.${getter}()).doesNotContain(${property_safe}); @@ -72,13 +72,12 @@ // we override the default error message with a more explicit one String assertjErrorMessage = "\nExpecting :\n <%s>\nnot to have ${property} but had :\n <%s>"; - - // check + + // check that it is not empty if (actual.${getter}().length > 0) { failWithMessage(assertjErrorMessage, actual, java.util.Arrays.toString(actual.${getter}())); } - + // return the current assertion for method chaining return ${myself}; } - \ No newline at end of file diff --git a/src/main/resources/templates/has_elements_assertion_template_for_iterable.txt b/src/main/resources/templates/has_elements_assertion_template_for_iterable.txt index 59befc5c..f3e42458 100644 --- a/src/main/resources/templates/has_elements_assertion_template_for_iterable.txt +++ b/src/main/resources/templates/has_elements_assertion_template_for_iterable.txt @@ -11,14 +11,14 @@ // check that given ${elementType} varargs is not null. if (${property_safe} == null) failWithMessage("Expecting ${property} parameter not to be null."); - + // check with standard error message, to set another message call: info.overridingErrorMessage("my error message"); Iterables.instance().assertContains(info, actual.${getter}(), ${property_safe}); // return the current assertion for method chaining return ${myself}; } - + /** * Verifies that the actual ${class_to_assert}'s ${property} contains the given ${elementType} elements in Collection. * @param ${property_safe} the given elements that should be contained in actual ${class_to_assert}'s ${property}. @@ -34,7 +34,7 @@ failWithMessage("Expecting ${property} parameter not to be null."); return ${myself}; // to fool Eclipse "Null pointer access" warning on toArray. } - + // check with standard error message, to set another message call: info.overridingErrorMessage("my error message"); Iterables.instance().assertContains(info, actual.${getter}(), ${property_safe}.toArray()); @@ -54,7 +54,7 @@ // check that given ${elementType} varargs is not null. if (${property_safe} == null) failWithMessage("Expecting ${property} parameter not to be null."); - + // check with standard error message, to set another message call: info.overridingErrorMessage("my error message"); Iterables.instance().assertContainsOnly(info, actual.${getter}(), ${property_safe}); @@ -77,7 +77,7 @@ failWithMessage("Expecting ${property} parameter not to be null."); return ${myself}; // to fool Eclipse "Null pointer access" warning on toArray. } - + // check with standard error message, to set another message call: info.overridingErrorMessage("my error message"); Iterables.instance().assertContainsOnly(info, actual.${getter}(), ${property_safe}.toArray()); @@ -98,7 +98,7 @@ // check that given ${elementType} varargs is not null. if (${property_safe} == null) failWithMessage("Expecting ${property} parameter not to be null."); - + // check with standard error message (use overridingErrorMessage before contains to set your own message). Iterables.instance().assertDoesNotContain(info, actual.${getter}(), ${property_safe}); @@ -122,7 +122,7 @@ failWithMessage("Expecting ${property} parameter not to be null."); return ${myself}; // to fool Eclipse "Null pointer access" warning on toArray. } - + // check with standard error message (use overridingErrorMessage before contains to set your own message). Iterables.instance().assertDoesNotContain(info, actual.${getter}(), ${property_safe}.toArray()); @@ -141,13 +141,12 @@ // we override the default error message with a more explicit one String assertjErrorMessage = "\nExpecting :\n <%s>\nnot to have ${property} but had :\n <%s>"; - + // check if (actual.${getter}().iterator().hasNext()) { failWithMessage(assertjErrorMessage, actual, actual.${getter}()); } - + // return the current assertion for method chaining return ${myself}; } - \ No newline at end of file diff --git a/src/main/resources/templates/is_assertion_template.txt b/src/main/resources/templates/is_assertion_template.txt index d1b8ead8..86b1e1be 100644 --- a/src/main/resources/templates/is_assertion_template.txt +++ b/src/main/resources/templates/is_assertion_template.txt @@ -8,11 +8,11 @@ // check that actual ${class_to_assert} we want to make assertions on is not null. isNotNull(); - // check + // check that property call/field access is true if (!actual.${predicate}()) { failWithMessage("\nExpecting that actual ${class_to_assert} ${predicate_for_error_message_part1} but ${predicate_for_error_message_part2}."); } - + // return the current assertion for method chaining return ${myself}; } @@ -26,11 +26,11 @@ // check that actual ${class_to_assert} we want to make assertions on is not null. isNotNull(); - // check + // check that property call/field access is false if (actual.${predicate}()) { failWithMessage("\nExpecting that actual ${class_to_assert} ${negative_predicate_for_error_message_part1} but ${negative_predicate_for_error_message_part2}."); } - + // return the current assertion for method chaining return ${myself}; } \ No newline at end of file diff --git a/src/main/resources/templates/is_wrapper_assertion_template.txt b/src/main/resources/templates/is_wrapper_assertion_template.txt index 36d4ceb1..44ea0ed1 100644 --- a/src/main/resources/templates/is_wrapper_assertion_template.txt +++ b/src/main/resources/templates/is_wrapper_assertion_template.txt @@ -12,7 +12,7 @@ if (Objects.areEqual(Boolean.FALSE, actual.${predicate}())) { failWithMessage("\nExpecting that actual ${class_to_assert} ${predicate_for_error_message_part1} but ${predicate_for_error_message_part2}."); } - + // return the current assertion for method chaining return ${myself}; } @@ -30,7 +30,7 @@ if (Objects.areEqual(Boolean.TRUE, actual.${predicate}())) { failWithMessage("\nExpecting that actual ${class_to_assert} ${negative_predicate_for_error_message_part1} but ${negative_predicate_for_error_message_part2}."); } - + // return the current assertion for method chaining return ${myself}; } \ No newline at end of file diff --git a/src/test/java/org/assertj/assertions/generator/AssertionGeneratorOverrideTemplateTest.java b/src/test/java/org/assertj/assertions/generator/AssertionGeneratorOverrideTemplateTest.java index a61318d5..c19a4e71 100644 --- a/src/test/java/org/assertj/assertions/generator/AssertionGeneratorOverrideTemplateTest.java +++ b/src/test/java/org/assertj/assertions/generator/AssertionGeneratorOverrideTemplateTest.java @@ -12,24 +12,27 @@ */ package org.assertj.assertions.generator; -import static org.assertj.assertions.generator.AssertionGeneratorTest.assertGeneratedAssertClass; - -import java.io.File; -import java.io.IOException; - import org.assertj.assertions.generator.data.cars.Car; import org.assertj.assertions.generator.description.converter.ClassToClassDescriptionConverter; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import java.io.File; +import java.io.IOException; +import java.nio.file.Paths; + public class AssertionGeneratorOverrideTemplateTest { private BaseAssertionGenerator assertionGenerator; private ClassToClassDescriptionConverter converter; + @Rule + public final GenerationPathHandler genHandle = new GenerationPathHandler(AssertionGeneratorOverrideTemplateTest.class, + Paths.get("src/test/resources")); + @Before public void before() throws IOException { - assertionGenerator = new BaseAssertionGenerator(); - assertionGenerator.setDirectoryWhereAssertionFilesAreGenerated("target"); + assertionGenerator = genHandle.buildAssertionGenerator(); converter = new ClassToClassDescriptionConverter(); } @@ -55,6 +58,6 @@ public void should_generate_assertion_with_custom_template() throws IOException "custom_has_assertion_template_for_whole_number.txt"))); assertionGenerator.generateCustomAssertionFor(converter.convertToClassDescription(Car.class)); - assertGeneratedAssertClass(Car.class, "CarAssert.expected.txt"); + genHandle.assertGeneratedAssertClass(Car.class, "CarAssert.expected.txt", true); } } diff --git a/src/test/java/org/assertj/assertions/generator/AssertionGeneratorTest.java b/src/test/java/org/assertj/assertions/generator/AssertionGeneratorTest.java index c31daacb..6555a42e 100644 --- a/src/test/java/org/assertj/assertions/generator/AssertionGeneratorTest.java +++ b/src/test/java/org/assertj/assertions/generator/AssertionGeneratorTest.java @@ -12,23 +12,15 @@ */ package org.assertj.assertions.generator; -import org.assertj.assertions.generator.data.AnnotatedClass; -import org.assertj.assertions.generator.data.ArtWork; -import org.assertj.assertions.generator.data.AutoValue; -import org.assertj.assertions.generator.data.AutoValueAnnotatedClass; -import org.assertj.assertions.generator.data.BooleanPredicates; -import org.assertj.assertions.generator.data.FieldPropertyClash; -import org.assertj.assertions.generator.data.InterferencePrimitives; -import org.assertj.assertions.generator.data.Keywords; -import org.assertj.assertions.generator.data.Movie; -import org.assertj.assertions.generator.data.Primitives; -import org.assertj.assertions.generator.data.Team; +import com.google.common.reflect.TypeToken; +import org.assertj.assertions.generator.data.*; import org.assertj.assertions.generator.data.nba.Player; import org.assertj.assertions.generator.data.nba.PlayerAgent; import org.assertj.assertions.generator.description.ClassDescription; import org.assertj.assertions.generator.description.converter.AnnotationConfiguration; import org.assertj.assertions.generator.description.converter.ClassToClassDescriptionConverter; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.experimental.theories.Theories; import org.junit.experimental.theories.Theory; @@ -38,121 +30,127 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Paths; import java.sql.SQLException; -import java.util.Collections; -import java.util.Set; +import java.util.*; -import static com.google.common.collect.Sets.newHashSet; import static java.lang.reflect.Modifier.isPublic; import static java.nio.charset.Charset.defaultCharset; import static org.apache.commons.lang3.StringUtils.replace; -import static org.assertj.assertions.generator.BaseAssertionGenerator.ABSTRACT_ASSERT_CLASS_PREFIX; -import static org.assertj.assertions.generator.BaseAssertionGenerator.ASSERT_CLASS_FILE_SUFFIX; -import static org.assertj.assertions.generator.util.ClassUtil.collectClasses; -import static org.assertj.assertions.generator.util.ClassUtil.getSimpleNameWithOuterClass; -import static org.assertj.assertions.generator.util.ClassUtil.getSimpleNameWithOuterClassNotSeparatedByDots; +import static org.assertj.assertions.generator.util.ClassUtil.*; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.contentOf; @RunWith(Theories.class) public class AssertionGeneratorTest implements NestedClassesTest, BeanWithExceptionsTest { - private static final String LINE_SEPARATOR = System.getProperty("line.separator"); - private static final String TARGET_DIRECTORY = "target"; - private static final File RESOURCES_DIRECTORY = new File("src/test/resources"); + private static final String LINE_SEPARATOR = "\n"; private static final Logger logger = LoggerFactory.getLogger(AssertionGeneratorTest.class); private ClassToClassDescriptionConverter converter; private AssertionGenerator assertionGenerator; - private static final Set> allClasses = newHashSet(new Class[] { Movie.class, ArtWork.class }); + private static final Set> allClasses = + new HashSet<>(Arrays.>asList(TypeToken.of(Movie.class), TypeToken.of(ArtWork.class))); + + @Rule + public final GenerationPathHandler genHandle = new GenerationPathHandler(AssertionGeneratorTest.class, Paths.get("src/test/resources")); @Before public void beforeEachTest() throws IOException { converter = new ClassToClassDescriptionConverter(); - assertionGenerator = buildAssertionGenerator(); - } - - public AssertionGenerator buildAssertionGenerator() throws IOException { - BaseAssertionGenerator assertionGenerator = new BaseAssertionGenerator(); - assertionGenerator.setDirectoryWhereAssertionFilesAreGenerated(TARGET_DIRECTORY); - return assertionGenerator; + assertionGenerator = genHandle.buildAssertionGenerator(); } @Test public void should_generate_assertion_for_player_class() throws Exception { assertionGenerator.generateCustomAssertionFor(converter.convertToClassDescription(Player.class)); - assertGeneratedAssertClass(Player.class, "PlayerAssert.expected.txt"); + genHandle.assertGeneratedAssertClass(Player.class, "PlayerAssert.expected.txt", true); } @Test public void should_generate_assertion_for_interface() throws Exception { assertionGenerator.generateCustomAssertionFor(converter.convertToClassDescription(PlayerAgent.class)); - assertGeneratedAssertClass(PlayerAgent.class, "PlayerAgentAssert.expected.txt"); + genHandle.assertGeneratedAssertClass(PlayerAgent.class, "PlayerAgentAssert.expected.txt", true); } @Test public void should_generate_assertion_for_class_with_public_fields() throws Exception { assertionGenerator.generateCustomAssertionFor(converter.convertToClassDescription(Team.class)); - assertGeneratedAssertClass(Team.class, "TeamAssert.expected.txt"); + genHandle.assertGeneratedAssertClass(Team.class, "TeamAssert.expected.txt", true); } @Test public void should_generate_assertion_for_class_with_properties_that_clash_with_fields() throws Exception { assertionGenerator.generateCustomAssertionFor(converter.convertToClassDescription(FieldPropertyClash.class)); - assertGeneratedAssertClass(FieldPropertyClash.class, "FieldPropertyClash.expected.txt"); + genHandle.assertGeneratedAssertClass(FieldPropertyClash.class, "FieldPropertyClash.expected.txt", true); } @Test public void should_generate_assertion_for_class_with_properties_that_clash_with_keywords() throws Exception { assertionGenerator.generateCustomAssertionFor(converter.convertToClassDescription(Keywords.class)); - assertGeneratedAssertClass(Keywords.class, "Keywords.expected.txt"); + genHandle.assertGeneratedAssertClass(Keywords.class, "Keywords.expected.txt", true); } @Test public void should_generate_assertion_for_class_with_predicates() throws Exception { - assertionGenerator.generateCustomAssertionFor(converter.convertToClassDescription(BooleanPredicates.class)); - assertGeneratedAssertClass(BooleanPredicates.class, "BooleanPredicates.expected.txt"); + ClassDescription classDescription = converter.convertToClassDescription(BooleanPredicates.class); + assertionGenerator.generateCustomAssertionFor(classDescription); + genHandle.assertGeneratedAssertClass(BooleanPredicates.class, "BooleanPredicates.expected.txt", true); } @Test public void should_generate_assertion_for_class_with_primitives() throws Exception { assertionGenerator.generateCustomAssertionFor(converter.convertToClassDescription(Primitives.class)); - assertGeneratedAssertClass(Primitives.class, "PrimitivesAssert.expected.txt"); + genHandle.assertGeneratedAssertClass(Primitives.class, "PrimitivesAssert.expected.txt", true); } @Test public void should_generate_assertion_for_class_with_interference_primitives() throws Exception { assertionGenerator.generateCustomAssertionFor(converter.convertToClassDescription(InterferencePrimitives.class)); - assertGeneratedAssertClass(InterferencePrimitives.class, "InterferencePrimitivesAssert.expected.txt"); + genHandle.assertGeneratedAssertClass(InterferencePrimitives.class, "InterferencePrimitivesAssert.expected.txt", true); } @Test public void should_generate_flat_assertion_for_movie_class() throws Exception { - abstractFileGeneratedFor(Movie.class).delete(); assertionGenerator.generateCustomAssertionFor(converter.convertToClassDescription(Movie.class)); - assertGeneratedAssertClass(Movie.class, "MovieAssert.flat.expected.txt"); - assertThat(abstractFileGeneratedFor(Movie.class)).doesNotExist(); + genHandle.assertGeneratedAssertClass(Movie.class, "MovieAssert.flat.expected.txt", true); + assertThat(genHandle.abstractFileGeneratedFor(Movie.class)).doesNotExist(); } @Test public void should_generate_hierarchical_assertion_for_movie_class() throws Exception { - assertionGenerator.generateHierarchicalCustomAssertionFor(converter.convertToClassDescription(Movie.class), - allClasses); - assertGeneratedAssertClass(Movie.class, "MovieAssert.expected.txt"); - assertAbstractGeneratedAssertClass(Movie.class, "AbstractMovieAssert.expected.txt"); + List generated = new ArrayList<>(4); + + File[] movieFiles = assertionGenerator.generateHierarchicalCustomAssertionFor(converter.convertToClassDescription(Movie.class), + allClasses); + generated.addAll(Arrays.asList(movieFiles)); + + genHandle.assertGeneratedAssertClass(Movie.class, "MovieAssert.expected.txt", false); + genHandle.assertAbstractGeneratedAssertClass(Movie.class, "AbstractMovieAssert.expected.txt"); + + // These should also be generated! + File[] artWorkFiles = assertionGenerator.generateHierarchicalCustomAssertionFor(converter.convertToClassDescription(ArtWork.class), + allClasses); + generated.addAll(Arrays.asList(artWorkFiles)); + genHandle.assertGeneratedAssertClass(ArtWork.class, "ArtWorkAssert.expected.txt", false); + genHandle.assertAbstractGeneratedAssertClass(ArtWork.class, "AbstractArtWorkAssert.expected.txt"); + + // compile them + genHandle.compileGeneratedFiles(generated); } @Test public void should_generate_hierarchical_assertion_for_artwork_class() throws Exception { assertionGenerator.generateHierarchicalCustomAssertionFor(converter.convertToClassDescription(ArtWork.class), - allClasses); - assertGeneratedAssertClass(ArtWork.class, "ArtWorkAssert.expected.txt"); - assertAbstractGeneratedAssertClass(ArtWork.class, "AbstractArtWorkAssert.expected.txt"); + allClasses); + + genHandle.assertAbstractGeneratedAssertClass(ArtWork.class, "AbstractArtWorkAssert.expected.txt"); + genHandle.assertGeneratedAssertClass(ArtWork.class, "ArtWorkAssert.expected.txt", true); } @Theory public void should_generate_assertion_for_nested_class(NestedClass nestedClass) throws Exception { Class clazz = nestedClass.getNestedClass(); assertionGenerator.generateCustomAssertionFor(converter.convertToClassDescription(clazz)); - assertThat(fileGeneratedFor(clazz)).hasContent(expectedContentFromTemplate(clazz, + assertThat(genHandle.fileGeneratedFor(clazz)).hasContent(expectedContentFromTemplate(clazz, "NestedClassAssert.template.expected.txt")); } @@ -160,21 +158,23 @@ public void should_generate_assertion_for_nested_class(NestedClass nestedClass) public void should_generate_hierarchical_assertion_for_nested_class(NestedClass nestedClass) throws Exception { Class clazz = nestedClass.getNestedClass(); assertionGenerator.generateHierarchicalCustomAssertionFor(converter.convertToClassDescription(clazz), null); - assertThat(fileGeneratedFor(clazz)).hasContent(expectedContentFromTemplate(clazz, + assertThat(genHandle.fileGeneratedFor(clazz)).hasContent(expectedContentFromTemplate(clazz, "NestedClassAssert.hierarchical.template.expected.txt")); } @Theory - public void should_generate_assertion_for_property_with_exception(Class beanClass) throws Exception { - assertionGenerator.generateCustomAssertionFor(converter.convertToClassDescription(beanClass)); - String expectedContent = contentOf(new File(RESOURCES_DIRECTORY, "BeanWithOneException.expected.txt"), defaultCharset()); - if (!BEAN_WITH_ONE_EXCEPTION.equals(beanClass)) { - expectedContent = expectedContent.replace(BEAN_WITH_ONE_EXCEPTION.getSimpleName(), beanClass.getSimpleName()); + public void should_generate_assertion_for_property_with_exception(TypeToken beanType) throws Exception { + assertionGenerator.generateCustomAssertionFor(converter.convertToClassDescription(beanType)); + Class clazz = beanType.getRawType(); + String expectedContent = contentOf(genHandle.getResourcesDir().resolve("BeanWithOneException.expected.txt").toFile(), defaultCharset()); + if (!BEAN_WITH_ONE_EXCEPTION.equals(beanType)) { + expectedContent = expectedContent.replace(BEAN_WITH_ONE_EXCEPTION.getRawType().getSimpleName(), clazz.getSimpleName()); expectedContent = expectedContent.replace(" throws java.io.IOException ", " throws java.io.IOException, java.sql.SQLException "); - GetterWithException[] getters = { STRING_1_EXCEPTION, BOOLEAN_1_EXCEPTION, ARRAY_1_EXCEPTION, - ITERABLE_1_EXCEPTION }; + List getters = Arrays.asList(STRING_1_EXCEPTION, BOOLEAN_1_EXCEPTION, ARRAY_1_EXCEPTION, + ITERABLE_1_EXCEPTION); + Collections.sort(getters); for (GetterWithException getter : getters) { String throwsClause = generateThrowsClause(IOException.class, getter.getPropertyName(), getter.isBooleanType()); String replacement = throwsClause @@ -183,13 +183,14 @@ public void should_generate_assertion_for_property_with_exception(Class beanC expectedContent = expectedContent.replace(throwsClause, replacement); } } - assertThat(fileGeneratedFor(beanClass)).hasContent(expectedContent); + assertThat(genHandle.fileGeneratedFor(clazz)).hasContent(expectedContent); } @Test public void should_generate_assertion_for_classes_in_package() throws Exception { - Set> classes = collectClasses("org.assertj.assertions.generator.data"); - for (Class clazz : classes) { + Set> classes = collectClasses("org.assertj.assertions.generator.data"); + for (TypeToken type : classes) { + Class clazz = type.getRawType(); assertThat(clazz.isAnonymousClass()).as("check that <" + clazz.getSimpleName() + "> is not anonymous").isFalse(); assertThat(clazz.isLocalClass()).as("check that " + clazz.getSimpleName() + " is not local").isFalse(); assertThat(isPublic(clazz.getModifiers())).as("check that " + clazz.getSimpleName() + " is public").isTrue(); @@ -203,8 +204,9 @@ public void should_generate_assertion_for_classes_in_package() throws Exception @Test public void should_generate_assertion_for_classes_in_package_using_provided_class_loader() throws Exception { ClassLoader customClassLoader = new MyClassLoader(Thread.currentThread().getContextClassLoader()); - Set> classes = collectClasses(customClassLoader, "org.assertj.assertions.generator.data"); - for (Class clazz : classes) { + Set> types = collectClasses(customClassLoader, "org.assertj.assertions.generator.data"); + for (TypeToken type : types) { + Class clazz = type.getRawType(); assertThat(clazz.isAnonymousClass()).as("check that " + clazz.getSimpleName() + " is not anonymous").isFalse(); assertThat(clazz.isLocalClass()).as("check that " + clazz.getSimpleName() + " is not local").isFalse(); assertThat(isPublic(clazz.getModifiers())).as("check that " + clazz.getSimpleName() + " is public").isTrue(); @@ -219,63 +221,42 @@ public void should_generate_assertion_for_classes_in_package_using_provided_clas public void should_generate_assertion_for_classes_using_type_with_same_name() throws IOException { Class clazz = ClassUsingDifferentClassesWithSameName.class; assertionGenerator.generateCustomAssertionFor(converter.convertToClassDescription(clazz)); - assertGeneratedAssertClass(ClassUsingDifferentClassesWithSameName.class, - "ClassUsingDifferentClassesWithSameName.expected.txt"); + genHandle.assertGeneratedAssertClass(ClassUsingDifferentClassesWithSameName.class, + "ClassUsingDifferentClassesWithSameName.expected.txt", true); } @Test public void should_generate_assertion_for_annotated_methods() throws IOException { converter = new ClassToClassDescriptionConverter(new AnnotationConfiguration(GenerateAssertion.class)); assertionGenerator.generateCustomAssertionFor(converter.convertToClassDescription(AnnotatedClass.class)); - assertGeneratedAssertClass(AnnotatedClass.class, "AnnotatedClassAssert.expected.txt"); + genHandle.assertGeneratedAssertClass(AnnotatedClass.class, "AnnotatedClassAssert.expected.txt", true); } @Test public void should_generate_assertion_for_methods_annotated_with_GenerateAssertion_by_default() throws IOException { assertionGenerator.generateCustomAssertionFor(converter.convertToClassDescription(AnnotatedClass.class)); - assertGeneratedAssertClass(AnnotatedClass.class, "AnnotatedClassAssert.expected.txt"); + genHandle.assertGeneratedAssertClass(AnnotatedClass.class, "AnnotatedClassAssert.expected.txt", true); } @Test public void should_generate_assertion_for_annotated_class() throws IOException { converter = new ClassToClassDescriptionConverter(new AnnotationConfiguration(AutoValue.class)); assertionGenerator.generateCustomAssertionFor(converter.convertToClassDescription(AutoValueAnnotatedClass.class)); - assertGeneratedAssertClass(AutoValueAnnotatedClass.class, "AutoValueAnnotatedClassAssert.expected.txt"); - } - - static void assertGeneratedAssertClass(Class clazz, String expectedAssertFile) { - File expectedFile = new File(RESOURCES_DIRECTORY, expectedAssertFile).getAbsoluteFile(); - assertThat(fileGeneratedFor(clazz)).hasSameContentAs(expectedFile); + genHandle.assertGeneratedAssertClass(AutoValueAnnotatedClass.class, "AutoValueAnnotatedClassAssert.expected.txt", true); } - private static void assertAbstractGeneratedAssertClass(Class clazz, String expectedAssertFile) { - File expectedFile = new File(RESOURCES_DIRECTORY, expectedAssertFile).getAbsoluteFile(); - assertThat(abstractFileGeneratedFor(clazz)).hasSameContentAs(expectedFile); - } - private static String expectedContentFromTemplate(Class clazz, String fileTemplate) throws IOException { - String template = contentOf(new File(RESOURCES_DIRECTORY, fileTemplate), defaultCharset()); + private String expectedContentFromTemplate(Class clazz, String fileTemplate) throws IOException { + String template = contentOf(genHandle.getResourcesDir().resolve(fileTemplate).toFile(), defaultCharset()); String content = replace(template, "${nestedClass}Assert", getSimpleNameWithOuterClassNotSeparatedByDots(clazz) + "Assert"); content = replace(content, "${nestedClass}", getSimpleNameWithOuterClass(clazz)); return content; } - private static File fileGeneratedFor(Class clazz) { - String dirName = TARGET_DIRECTORY + File.separatorChar - + clazz.getPackage().getName().replace('.', File.separatorChar); - String generatedFileName = getSimpleNameWithOuterClassNotSeparatedByDots(clazz) + ASSERT_CLASS_FILE_SUFFIX; - return new File(dirName, generatedFileName); - } - private static File abstractFileGeneratedFor(Class clazz) { - String dirName = TARGET_DIRECTORY + File.separatorChar - + clazz.getPackage().getName().replace('.', File.separatorChar); - String generatedFileName = ABSTRACT_ASSERT_CLASS_PREFIX + getSimpleNameWithOuterClassNotSeparatedByDots(clazz) - + ASSERT_CLASS_FILE_SUFFIX; - return new File(dirName, generatedFileName); - } + @SuppressWarnings("WeakerAccess") class MyClassLoader extends ClassLoader { public MyClassLoader(ClassLoader parent) { super(parent); diff --git a/src/test/java/org/assertj/assertions/generator/AssertionsEntryPointGeneratorTest.java b/src/test/java/org/assertj/assertions/generator/AssertionsEntryPointGeneratorTest.java index 1f31f02a..767fd886 100644 --- a/src/test/java/org/assertj/assertions/generator/AssertionsEntryPointGeneratorTest.java +++ b/src/test/java/org/assertj/assertions/generator/AssertionsEntryPointGeneratorTest.java @@ -12,26 +12,7 @@ */ package org.assertj.assertions.generator; -import static com.google.common.collect.Sets.newLinkedHashSet; -import static org.assertj.assertions.generator.AssertionsEntryPointType.AUTO_CLOSEABLE_BDD_SOFT; -import static org.assertj.assertions.generator.AssertionsEntryPointType.AUTO_CLOSEABLE_SOFT; -import static org.assertj.assertions.generator.AssertionsEntryPointType.BDD; -import static org.assertj.assertions.generator.AssertionsEntryPointType.BDD_SOFT; -import static org.assertj.assertions.generator.AssertionsEntryPointType.JUNIT_BDD_SOFT; -import static org.assertj.assertions.generator.AssertionsEntryPointType.JUNIT_SOFT; -import static org.assertj.assertions.generator.AssertionsEntryPointType.SOFT; -import static org.assertj.assertions.generator.AssertionsEntryPointType.STANDARD; -import static org.assertj.assertions.generator.DefaultTemplateRegistryProducer.DEFAULT_ASSERTIONS_ENTRY_POINT_CLASS_TEMPLATE; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.contentOf; - -import java.io.File; -import java.io.IOException; -import java.util.LinkedHashSet; -import java.util.Set; - -import org.junit.Before; -import org.junit.Test; +import com.google.common.reflect.TypeToken; import org.assertj.assertions.generator.data.ArtWork; import org.assertj.assertions.generator.data.Movie; import org.assertj.assertions.generator.data.Name; @@ -43,14 +24,31 @@ import org.assertj.assertions.generator.data.nba.Team; import org.assertj.assertions.generator.description.ClassDescription; import org.assertj.assertions.generator.description.converter.ClassToClassDescriptionConverter; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Paths; +import java.util.LinkedHashSet; +import java.util.Set; + +import static com.google.common.collect.Sets.newLinkedHashSet; +import static org.assertj.assertions.generator.AssertionsEntryPointType.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.contentOf; public class AssertionsEntryPointGeneratorTest { - private static final String TARGET_DIRECTORY = "target"; private BaseAssertionGenerator generator; + @Rule + public final GenerationPathHandler genHandle = new GenerationPathHandler(AssertionsEntryPointGeneratorTest.class, + Paths.get("src/test/resources")); + @Before public void beforeEachTest() throws IOException { - generator = buildAssertionGenerator(); + generator = genHandle.buildAssertionGenerator(); } @Test @@ -94,7 +92,7 @@ public void should_generate_assertion_entry_point_class_file_with_custom_package String expectedContent = readExpectedContentFromFile("AssertionsWithCustomPackage.expected.txt"); assertThat(assertionsEntryPointFile).as("check entry point class content") .hasContent(expectedContent) - .hasParent("target/my/custom/package"); + .hasParent(genHandle.getRoot().toPath().resolve("my/custom/package").toFile()); } @Test @@ -269,17 +267,11 @@ private Set getClassDescriptionsOf(Class... classes) { Set classDescriptionSet = new LinkedHashSet<>(classes.length); ClassToClassDescriptionConverter converter = new ClassToClassDescriptionConverter(); for (Class clazz : classes) { - classDescriptionSet.add(converter.convertToClassDescription(clazz)); + classDescriptionSet.add(converter.convertToClassDescription(TypeToken.of(clazz))); } return classDescriptionSet; } - private BaseAssertionGenerator buildAssertionGenerator() throws IOException { - BaseAssertionGenerator assertionGenerator = new BaseAssertionGenerator(); - assertionGenerator.setDirectoryWhereAssertionFilesAreGenerated(TARGET_DIRECTORY); - return assertionGenerator; - } - private String readExpectedContentFromFile(String fileWithExpectedContent) { return contentOf(new File("src/test/resources", fileWithExpectedContent)); } diff --git a/src/test/java/org/assertj/assertions/generator/BeanWithExceptionsTest.java b/src/test/java/org/assertj/assertions/generator/BeanWithExceptionsTest.java index a09c0dce..498c63fb 100644 --- a/src/test/java/org/assertj/assertions/generator/BeanWithExceptionsTest.java +++ b/src/test/java/org/assertj/assertions/generator/BeanWithExceptionsTest.java @@ -12,79 +12,84 @@ */ package org.assertj.assertions.generator; +import com.google.common.collect.ImmutableList; +import com.google.common.reflect.TypeToken; import org.assertj.assertions.generator.data.BeanWithOneException; import org.assertj.assertions.generator.data.BeanWithTwoExceptions; -import org.assertj.assertions.generator.description.TypeName; - import org.junit.experimental.theories.DataPoint; import java.io.IOException; import java.sql.SQLException; -import java.util.ArrayList; import java.util.List; /** * This interface contains a set of constants for testing generation from {@link org.assertj.assertions.generator.data.BeanWithOneException} class. */ public interface BeanWithExceptionsTest { - static final Class[] ONE_EXCEPTION = new Class[]{IOException.class}; - static final Class[] TWO_EXCEPTIONS = new Class[]{IOException.class, SQLException.class}; - + List> ONE_EXCEPTION = + ImmutableList.>of(TypeToken.of(IOException.class)); + List> TWO_EXCEPTIONS = + ImmutableList.>of(TypeToken.of(IOException.class), + TypeToken.of(SQLException.class)); @DataPoint - public static final Class BEAN_WITH_ONE_EXCEPTION = BeanWithOneException.class; + TypeToken BEAN_WITH_ONE_EXCEPTION = TypeToken.of(BeanWithOneException.class); @DataPoint - public static final Class BEAN_WITH_TWO_EXCEPTIONS = BeanWithTwoExceptions.class; + TypeToken BEAN_WITH_TWO_EXCEPTIONS = TypeToken.of(BeanWithTwoExceptions.class); @DataPoint - public static final GetterWithException STRING_1_EXCEPTION = new GetterWithException(BEAN_WITH_ONE_EXCEPTION, "stringPropertyThrowsException", ONE_EXCEPTION, false); + GetterWithException STRING_1_EXCEPTION = new GetterWithException(BEAN_WITH_ONE_EXCEPTION, "stringPropertyThrowsException", ONE_EXCEPTION, false); @DataPoint - public static final GetterWithException STRING_2_EXCEPTIONS = new GetterWithException(BEAN_WITH_TWO_EXCEPTIONS, "stringPropertyThrowsException", TWO_EXCEPTIONS, false); + GetterWithException STRING_2_EXCEPTIONS = new GetterWithException(BEAN_WITH_TWO_EXCEPTIONS, "stringPropertyThrowsException", TWO_EXCEPTIONS, false); @DataPoint - public static final GetterWithException BOOLEAN_1_EXCEPTION = new GetterWithException(BEAN_WITH_ONE_EXCEPTION, "booleanPropertyThrowsException", ONE_EXCEPTION, true); + GetterWithException BOOLEAN_1_EXCEPTION = new GetterWithException(BEAN_WITH_ONE_EXCEPTION, "booleanPropertyThrowsException", ONE_EXCEPTION, true); @DataPoint - public static final GetterWithException BOOLEAN_2_EXCEPTIONS = new GetterWithException(BEAN_WITH_TWO_EXCEPTIONS, "booleanPropertyThrowsException", TWO_EXCEPTIONS, true); + GetterWithException BOOLEAN_2_EXCEPTIONS = new GetterWithException(BEAN_WITH_TWO_EXCEPTIONS, "booleanPropertyThrowsException", TWO_EXCEPTIONS, true); @DataPoint - public static final GetterWithException ARRAY_1_EXCEPTION = new GetterWithException(BEAN_WITH_ONE_EXCEPTION, "arrayPropertyThrowsException", ONE_EXCEPTION, false); + GetterWithException ARRAY_1_EXCEPTION = new GetterWithException(BEAN_WITH_ONE_EXCEPTION, "arrayPropertyThrowsException", ONE_EXCEPTION, false); @DataPoint - public static final GetterWithException ARRAY_2_EXCEPTIONS = new GetterWithException(BEAN_WITH_TWO_EXCEPTIONS, "arrayPropertyThrowsException", TWO_EXCEPTIONS, false); + GetterWithException ARRAY_2_EXCEPTIONS = new GetterWithException(BEAN_WITH_TWO_EXCEPTIONS, "arrayPropertyThrowsException", TWO_EXCEPTIONS, false); @DataPoint - public static final GetterWithException ITERABLE_1_EXCEPTION = new GetterWithException(BEAN_WITH_ONE_EXCEPTION, "iterablePropertyThrowsException", ONE_EXCEPTION, false); + GetterWithException ITERABLE_1_EXCEPTION = new GetterWithException(BEAN_WITH_ONE_EXCEPTION, "iterablePropertyThrowsException", ONE_EXCEPTION, false); @DataPoint - public static final GetterWithException ITERABLE_2_EXCEPTIONS = new GetterWithException(BEAN_WITH_TWO_EXCEPTIONS, "iterablePropertyThrowsException", TWO_EXCEPTIONS, false); + GetterWithException ITERABLE_2_EXCEPTIONS = new GetterWithException(BEAN_WITH_TWO_EXCEPTIONS, "iterablePropertyThrowsException", TWO_EXCEPTIONS, false); - public static class GetterWithException { - private final Class beanClass; + class GetterWithException implements Comparable { + private final TypeToken beanClass; private final String propertyName; - private final List exceptions; + private final List> exceptions; private final boolean booleanType; - public GetterWithException(Class beanClass, String propertyName, Class[] exceptions, boolean booleanType) { + public GetterWithException(TypeToken beanClass, + String propertyName, + List> exceptions, + boolean booleanType) { this.beanClass = beanClass; this.propertyName = propertyName; this.booleanType = booleanType; - List list = new ArrayList(exceptions.length); - for (Class exception : exceptions) { - list.add(new TypeName(exception)); - } - this.exceptions = list; + this.exceptions = exceptions; } public String getPropertyName() { return propertyName; } - public TypeName[] getExceptions() { - return exceptions.toArray(new TypeName[exceptions.size()]); + public List> getExceptions() { + return exceptions; } - public Class getBeanClass() { + public TypeToken getBeanClass() { return beanClass; } public boolean isBooleanType() { return booleanType; } + + @Override + public int compareTo(GetterWithException o) { + return propertyName.compareTo(o.propertyName); + } } } diff --git a/src/test/java/org/assertj/assertions/generator/GenerationPathHandler.java b/src/test/java/org/assertj/assertions/generator/GenerationPathHandler.java new file mode 100644 index 00000000..1291ae37 --- /dev/null +++ b/src/test/java/org/assertj/assertions/generator/GenerationPathHandler.java @@ -0,0 +1,211 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2012-2015 the original author or authors. + */ +package org.assertj.assertions.generator; + +import com.google.common.base.Joiner; +import com.google.testing.compile.Compilation; +import com.google.testing.compile.CompilationSubject; +import com.google.testing.compile.Compiler; +import com.google.testing.compile.JavaFileObjects; +import org.assertj.core.api.Assertions; +import org.junit.rules.TemporaryFolder; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +import javax.tools.JavaFileObject; +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; + +import static org.assertj.assertions.generator.BaseAssertionGenerator.ABSTRACT_ASSERT_CLASS_PREFIX; +import static org.assertj.assertions.generator.BaseAssertionGenerator.ASSERT_CLASS_FILE_SUFFIX; +import static org.assertj.assertions.generator.util.ClassUtil.getSimpleNameWithOuterClassNotSeparatedByDots; +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Test {@link org.junit.Rule} used to generate temporary folders per test case so there is no concern of + * tests interacting with each other. This utilizes the built-in {@link TemporaryFolder} to accomplish this and + * contains generator specific methods. + */ +public class GenerationPathHandler extends TemporaryFolder { + + + public static final Path DEFAULT_GENERATION_ROOT = Paths.get("target/generated-test-output"); + + private final Compiler compiler; + private Path resourcesDir; + + public GenerationPathHandler(final Class owningClass, Path resourcesDir) { + super(DEFAULT_GENERATION_ROOT.toFile()); + + //noinspection ResultOfMethodCallIgnored + DEFAULT_GENERATION_ROOT.toFile().mkdirs(); + + this.resourcesDir = resourcesDir; + + final String currentClasspath = getClasspathFromClassloader(ClassLoader.getSystemClassLoader()); + compiler = Compiler.javac() + .withOptions("-classpath", currentClasspath); + } + + public Path getResourcesDir() { + return resourcesDir; + } + + @Override + public Statement apply(final Statement base, final Description description) { + + return new Statement() { + @Override + public void evaluate() throws Throwable { + before(); + + try { + base.evaluate(); + after(); + } catch (Exception e) { + System.err.println("Failed working with folder: " + getRoot()); + throw new AssertionError(e); + } + } + }; + } + + public BaseAssertionGenerator buildAssertionGenerator() throws IOException { + BaseAssertionGenerator assertionGenerator = new BaseAssertionGenerator(); + assertionGenerator.setDirectoryWhereAssertionFilesAreGenerated(getRoot()); + return assertionGenerator; + } + + public Path packagePathFor(Class clazz) { + return getRoot().toPath() + .resolve(clazz.getPackage().getName().replace('.', File.separatorChar)); + } + + public File fileGeneratedFor(Class clazz) { + String generatedFileName = getSimpleNameWithOuterClassNotSeparatedByDots(clazz) + ASSERT_CLASS_FILE_SUFFIX; + return packagePathFor(clazz) + .resolve(generatedFileName) + .toFile(); + } + + public File abstractFileGeneratedFor(Class clazz) { + String generatedFileName = ABSTRACT_ASSERT_CLASS_PREFIX + + getSimpleNameWithOuterClassNotSeparatedByDots(clazz) + + ASSERT_CLASS_FILE_SUFFIX; + return packagePathFor(clazz) + .resolve(generatedFileName) + .toFile(); + } + + public void compileGeneratedFiles(Iterable files) { + List jfiles = new ArrayList<>(); + for (File file: files) { + try { + final URL url = file.toURI().toURL(); + jfiles.add(JavaFileObjects.forResource(url)); + } catch (MalformedURLException mfue) { + Assertions.failBecauseExceptionWasNotThrown(MalformedURLException.class); + } + } + + Compilation compilation = compiler.compile(jfiles); + + try { + + CompilationSubject.assertThat(compilation).succeeded(); + } catch (AssertionError ex) { + throw new AssertionError("Error with compilation. JAVAC options:\n" + compiler.options(), ex); + } + } + + public void compileGeneratedFiles(File... files) { + compileGeneratedFiles(Arrays.asList(files)); + } + + public void compileGeneratedFiles(Class... classes) { + List files = new ArrayList<>(classes.length); + for (Class clazz: classes) { + files.add(fileGeneratedFor(clazz)); + + // Handle abstract files, too! + File abstractFile = abstractFileGeneratedFor(clazz); + if (abstractFile.exists()) { + files.add(abstractFile); + } + } + + compileGeneratedFiles(files); + } + + public void assertGeneratedAssertClass(Class clazz, String expectedAssertFile, final boolean compileGenerated) throws IOException { + File expectedFile = resourcesDir.resolve(expectedAssertFile).toAbsolutePath().toFile(); + File actualFile = fileGeneratedFor(clazz); + assertThat(actualFile).hasSameContentAs(expectedFile); + + // compile it! + if (compileGenerated) { + compileGeneratedFiles(clazz); + } + } + + public void assertAbstractGeneratedAssertClass(Class clazz, String expectedAssertFile) { + File expectedFile = getResourcesDir().resolve(expectedAssertFile).toAbsolutePath().toFile(); + assertThat(abstractFileGeneratedFor(clazz)).hasSameContentAs(expectedFile); + } + + /** + * Returns the current classpaths of the given classloader including its parents. + * + * @throws IllegalArgumentException if the given classloader had classpaths which we could not + * determine or use for compilation. + */ + private static String getClasspathFromClassloader(ClassLoader currentClassloader) { + ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); + + // Add all URLClassloaders in the hirearchy till the system classloader. + List classloaders = new ArrayList<>(); + while(true) { + if (currentClassloader instanceof URLClassLoader) { + // We only know how to extract classpaths from URLClassloaders. + classloaders.add((URLClassLoader) currentClassloader); + } else { + throw new IllegalArgumentException("Classpath for compilation could not be extracted " + + "since given classloader is not an instance of URLClassloader"); + } + if (currentClassloader == systemClassLoader) { + break; + } + currentClassloader = currentClassloader.getParent(); + } + + Set classpaths = new LinkedHashSet<>(); + for (URLClassLoader classLoader : classloaders) { + for (URL url : classLoader.getURLs()) { + if (url.getProtocol().equals("file")) { + classpaths.add(url.getPath()); + } else { + throw new IllegalArgumentException("Given classloader consists of classpaths which are " + + "unsupported for compilation."); + } + } + } + + return Joiner.on(File.pathSeparatorChar).join(classpaths); + } +} diff --git a/src/test/java/org/assertj/assertions/generator/data/FieldPropertyClash.java b/src/test/java/org/assertj/assertions/generator/data/FieldPropertyClash.java index 63f55e9c..7abc35fd 100644 --- a/src/test/java/org/assertj/assertions/generator/data/FieldPropertyClash.java +++ b/src/test/java/org/assertj/assertions/generator/data/FieldPropertyClash.java @@ -20,4 +20,24 @@ public class FieldPropertyClash { public String getString() { return ""; } + + // joel-costigliola/assertj-assertions-generator#105 + // Predicate properties were not properly discerned vs non-predicate + public boolean isBoolean; + public boolean isBoolean() { return false; } + + public boolean isNotBoolean() { return false; } + + + public boolean shouldNotBeSomewhere; + public boolean shouldNotBeSomewhere() { return shouldNotBeSomewhere; } + + // different "tenses" + public boolean willBeOutside; + public boolean willNotBeOutside() { return willBeOutside; } + + // + public boolean willNotBeUpsideDown; + public boolean willBeUpsideDown() { return !willNotBeUpsideDown; } + } diff --git a/src/test/java/org/assertj/assertions/generator/data/Keywords.java b/src/test/java/org/assertj/assertions/generator/data/Keywords.java index 0bed7725..a98377bc 100644 --- a/src/test/java/org/assertj/assertions/generator/data/Keywords.java +++ b/src/test/java/org/assertj/assertions/generator/data/Keywords.java @@ -23,6 +23,7 @@ public class Keywords { public String getAbstract() throws java.io.IOException { return null; } + public Object getAssert() { return null; } diff --git a/src/test/java/org/assertj/assertions/generator/data/nba/Player.java b/src/test/java/org/assertj/assertions/generator/data/nba/Player.java index 29ddabe0..90441c4f 100644 --- a/src/test/java/org/assertj/assertions/generator/data/nba/Player.java +++ b/src/test/java/org/assertj/assertions/generator/data/nba/Player.java @@ -12,32 +12,39 @@ */ package org.assertj.assertions.generator.data.nba; -import static java.lang.String.format; -import static org.assertj.core.util.Objects.areEqual; +import org.assertj.assertions.generator.data.Name; import java.util.ArrayList; import java.util.List; -import org.assertj.assertions.generator.data.Name; +import static java.lang.String.format; +import static org.assertj.core.util.Objects.areEqual; /** * @author Joel Costigliola */ +@SuppressWarnings("unused") public class Player { private Name name; private boolean rookie; private int pointsPerGame; + private Integer pointerPerGameWrapped; private int assistsPerGame; private int reboundsPerGame; private String team; private float size; + private Float sizeAsFloatWrapper; + private double sizeDouble; + private Double sizeAsDoubleWrapper; // boolean property to test #46 private boolean isDisabled; private List teamMates = new ArrayList(); private List points = new ArrayList(); private String[] previousTeams = {}; + private boolean bad; + public Player(Name name, String team) { setName(name); setTeam(team); @@ -111,6 +118,38 @@ public boolean isRookie() { return rookie; } + public boolean wasRookie() { + return rookie; + } + + public boolean shouldWin() { + return false; + } + + public boolean canWin() { + return false; + } + + public boolean willWin() { + return false; + } + + public boolean cannotWin() { + return !canWin(); + } + + public boolean hasTrophy() { + return false; + } + + public boolean doesNotHaveFun() { + return false; + } + + public boolean shouldNotPlay() { + return false; + } + public void setRookie(boolean rookie) { this.rookie = rookie; } diff --git a/src/test/java/org/assertj/assertions/generator/description/FieldDescriptionTest.java b/src/test/java/org/assertj/assertions/generator/description/FieldDescriptionTest.java index 64ee11f3..aae6cc6e 100644 --- a/src/test/java/org/assertj/assertions/generator/description/FieldDescriptionTest.java +++ b/src/test/java/org/assertj/assertions/generator/description/FieldDescriptionTest.java @@ -12,87 +12,76 @@ */ package org.assertj.assertions.generator.description; -import static org.assertj.core.api.Assertions.assertThat; - +import com.google.common.reflect.TypeToken; +import org.assertj.assertions.generator.data.Name; import org.assertj.assertions.generator.data.nba.Player; import org.junit.Test; +import static org.assertj.core.api.Assertions.assertThat; + public class FieldDescriptionTest { - private DataDescription fieldDescription; - private TypeDescription boolDesc; + private static final TypeToken PLAYER_TYPE = TypeToken.of(Player.class); + private FieldDescription fieldDescription; @Test - public void should_create_valid_typename_from_class() { - fieldDescription = new FieldDescription("bestPlayer", new TypeDescription(new TypeName(Player.class))); - assertThat(fieldDescription.getName()).isEqualTo("bestPlayer"); - assertThat(fieldDescription.getTypeName()).isEqualTo("Player"); + public void should_create_valid_typename_from_class() throws Exception { + fieldDescription = new FieldDescription(Player.class.getDeclaredField("name"), PLAYER_TYPE); + assertThat(fieldDescription.getName()).isEqualTo("name"); + assertThat(fieldDescription.getTypeName(false, false)).isEqualTo(Name.class.getSimpleName()); assertThat(fieldDescription.getElementTypeName(Player.class.getPackage().getName())).isNull(); - boolDesc = new TypeDescription(new TypeName(boolean.class)); } @Test - public void should_show_information_in_toString() { - fieldDescription = new FieldDescription("bestPlayer", new TypeDescription(new TypeName(Player.class))); - assertThat(fieldDescription.toString()).contains("bestPlayer").contains(Player.class.getName()); + public void should_show_information_in_toString() throws Exception { + fieldDescription = new FieldDescription(Player.class.getDeclaredField("name"), PLAYER_TYPE); + assertThat(fieldDescription.toString()).contains("name") + .contains(Player.class.getName()) + .contains(Name.class.getName()); } @Test public void should_detect_real_number_correctly() throws Exception { - fieldDescription = new FieldDescription("double", new TypeDescription(new TypeName(double.class))); + fieldDescription = new FieldDescription(Player.class.getDeclaredField("sizeDouble"), PLAYER_TYPE); assertThat(fieldDescription.isRealNumberType()).as("double").isTrue(); - fieldDescription = new FieldDescription("Double", new TypeDescription(new TypeName(Double.class))); + fieldDescription = new FieldDescription(Player.class.getDeclaredField("sizeAsDoubleWrapper"), PLAYER_TYPE); assertThat(fieldDescription.isRealNumberType()).as("Double").isTrue(); - fieldDescription = new FieldDescription("float", new TypeDescription(new TypeName(float.class))); + fieldDescription = new FieldDescription(Player.class.getDeclaredField("size"), PLAYER_TYPE); assertThat(fieldDescription.isRealNumberType()).as("float").isTrue(); - fieldDescription = new FieldDescription("Float", new TypeDescription(new TypeName(Float.class))); + fieldDescription = new FieldDescription(Player.class.getDeclaredField("sizeAsFloatWrapper"), PLAYER_TYPE); assertThat(fieldDescription.isRealNumberType()).as("Float").isTrue(); + // not real number types - fieldDescription = new FieldDescription("int", new TypeDescription(new TypeName(int.class))); + fieldDescription = new FieldDescription(Player.class.getDeclaredField("pointsPerGame"), PLAYER_TYPE); assertThat(fieldDescription.isRealNumberType()).as("int").isFalse(); - fieldDescription = new FieldDescription("Integer", new TypeDescription(new TypeName(Integer.class))); + fieldDescription = new FieldDescription(Player.class.getDeclaredField("pointsPerGame"), PLAYER_TYPE); assertThat(fieldDescription.isRealNumberType()).as("Integer").isFalse(); - fieldDescription = new FieldDescription("String", new TypeDescription(new TypeName(String.class))); + fieldDescription = new FieldDescription(Player.class.getDeclaredField("team"), PLAYER_TYPE); assertThat(fieldDescription.isRealNumberType()).as("String").isFalse(); } - @Test - public void should_detect_predicate_correctly() throws Exception { - TypeDescription boolDesc = new TypeDescription(new TypeName(boolean.class)); - String[] list = new String[] { "anything", "isSomething", "somethingElse" }; - for (String p : list) { - fieldDescription = new FieldDescription(p, boolDesc); - assertThat(fieldDescription.isPredicate()).as(p + ":bool").isTrue(); - } - TypeDescription floatDesc = new TypeDescription(new TypeName(float.class)); - for (String p : list) { - fieldDescription = new FieldDescription(p, floatDesc); - assertThat(fieldDescription.isPredicate()).as(p + ":float").isFalse(); - } - } - @Test public void should_generate_default_predicate_correctly() throws Exception { - fieldDescription = new FieldDescription("bad", boolDesc); + fieldDescription = new FieldDescription(Player.class.getDeclaredField("bad"), PLAYER_TYPE); assertThat(fieldDescription.getNegativePredicate()).as("negative").isEqualTo("isNotBad"); assertThat(fieldDescription.getPredicate()).as("positive").isEqualTo("isBad"); } @Test - public void should_generate_readable_predicate_for_javadoc() { - fieldDescription = new FieldDescription("bad", boolDesc); + public void should_generate_readable_predicate_for_javadoc() throws Exception { + fieldDescription = new FieldDescription(Player.class.getDeclaredField("bad"), PLAYER_TYPE); assertThat(fieldDescription.getPredicateForJavadoc()).isEqualTo("is bad"); assertThat(fieldDescription.getNegativePredicateForJavadoc()).isEqualTo("is not bad"); } @Test - public void should_generate_readable_predicate_for_error_message() { - fieldDescription = new FieldDescription("bad", boolDesc); + public void should_generate_readable_predicate_for_error_message() throws Exception { + fieldDescription = new FieldDescription(Player.class.getDeclaredField("bad"), PLAYER_TYPE); assertThat(fieldDescription.getPredicateForErrorMessagePart1()).isEqualTo("is bad"); assertThat(fieldDescription.getPredicateForErrorMessagePart2()).isEqualTo("is not"); - fieldDescription = new FieldDescription("canBeGood", boolDesc); - assertThat(fieldDescription.getPredicateForErrorMessagePart1()).isEqualTo("can be good"); - assertThat(fieldDescription.getPredicateForErrorMessagePart2()).isEqualTo("cannot"); + fieldDescription = new FieldDescription(Player.class.getDeclaredField("isDisabled"), PLAYER_TYPE); + assertThat(fieldDescription.getPredicateForErrorMessagePart1()).isEqualTo("is disabled"); + assertThat(fieldDescription.getPredicateForErrorMessagePart2()).isEqualTo("is not"); } } diff --git a/src/test/java/org/assertj/assertions/generator/description/GetterDescriptionTest.java b/src/test/java/org/assertj/assertions/generator/description/GetterDescriptionTest.java index a519d9bd..eacb67f2 100644 --- a/src/test/java/org/assertj/assertions/generator/description/GetterDescriptionTest.java +++ b/src/test/java/org/assertj/assertions/generator/description/GetterDescriptionTest.java @@ -12,130 +12,124 @@ */ package org.assertj.assertions.generator.description; -import static org.assertj.core.api.Assertions.assertThat; - -import java.util.Collections; -import java.util.List; - +import com.google.common.reflect.TypeToken; import org.assertj.assertions.generator.data.nba.Player; +import org.junit.BeforeClass; import org.junit.Test; +import java.lang.reflect.Method; + +import static org.assertj.core.api.Assertions.assertThat; + public class GetterDescriptionTest { - private static final TypeDescription PLAYER_TYPE_DESCRIPTION = new TypeDescription(new TypeName(Player.class)); - private static final TypeDescription BOOLEAN_TYPE_DESCRIPTION = new TypeDescription(new TypeName(boolean.class)); - private static final List EMPTY_TYPENAME_LIST = Collections. emptyList();; + private static final TypeToken PLAYER_TYPE_DESCRIPTION = TypeToken.of(Player.class); private GetterDescription getterDescription; - @Test - public void should_create_valid_typename_from_class() { - getterDescription = new GetterDescription("bestPlayer", "getBestPlayer", PLAYER_TYPE_DESCRIPTION, - EMPTY_TYPENAME_LIST); - assertThat(getterDescription.getPropertyName()).isEqualTo("bestPlayer"); - assertThat(getterDescription.getTypeName()).isEqualTo("Player"); - assertThat(getterDescription.getElementTypeName(Player.class.getPackage().getName())).isNull(); + private static Method PLAYER_GET_POINTS_METHOD; + + @BeforeClass + public static void setupClass() throws Exception { + PLAYER_GET_POINTS_METHOD = Player.class.getMethod("getPoints"); } @Test - public void should_show_information_in_toString() { - getterDescription = new GetterDescription("bestPlayer", "getBestPlayer", PLAYER_TYPE_DESCRIPTION, - EMPTY_TYPENAME_LIST); - assertThat(getterDescription.toString()).contains("bestPlayer").contains(Player.class.getName()); + public void should_create_valid_typename_from_class() throws Exception { + getterDescription = new GetterDescription("points", PLAYER_TYPE_DESCRIPTION, PLAYER_GET_POINTS_METHOD); + assertThat(getterDescription.getName()).isEqualTo("points"); + assertThat(getterDescription.getTypeName(false, false)).isEqualTo("List"); + assertThat(getterDescription.getElementTypeName(Player.class.getPackage().getName())).isEqualTo("int[]"); } @Test - public void should_not_be_predicate() { - getterDescription = new GetterDescription("bestPlayer", "getBestPlayer", PLAYER_TYPE_DESCRIPTION, - EMPTY_TYPENAME_LIST); - assertThat(getterDescription.isPredicate()).as("bestPlayer").isFalse(); - getterDescription = new GetterDescription("runFlag", "getRunFlag", BOOLEAN_TYPE_DESCRIPTION, EMPTY_TYPENAME_LIST); - assertThat(getterDescription.isPredicate()).as("runFlag").isFalse(); + public void should_show_information_in_toString() throws Exception { + getterDescription = new GetterDescription("points", PLAYER_TYPE_DESCRIPTION, PLAYER_GET_POINTS_METHOD); + assertThat(getterDescription.toString()).contains("points").contains("List"); } @Test - public void should_be_predicate() { - for (String p : new String[] { "is", "can", "was", "has", "should" }) { - getterDescription = new GetterDescription("bestPlayer", p + "BestPlayer", BOOLEAN_TYPE_DESCRIPTION, - EMPTY_TYPENAME_LIST); - assertThat(getterDescription.isPredicate()).as(p).isTrue(); - } + public void should_not_be_predicate() throws Exception { + getterDescription = new GetterDescription("points", PLAYER_TYPE_DESCRIPTION, PLAYER_GET_POINTS_METHOD); + assertThat(getterDescription.isPredicate()).as("points").isFalse(); + getterDescription = new GetterDescription("rookie", PLAYER_TYPE_DESCRIPTION, Player.class.getMethod("isRookie")); + assertThat(getterDescription.isPredicate()).as("rookie").isTrue(); } @Test - public void should_generate_predicate_for_javadoc() { - getterDescription = new GetterDescription("rookie", "isRookie", BOOLEAN_TYPE_DESCRIPTION, EMPTY_TYPENAME_LIST); + public void should_generate_predicate_for_javadoc() throws Exception { + getterDescription = new GetterDescription("rookie", PLAYER_TYPE_DESCRIPTION, Player.class.getMethod("isRookie")); assertThat(getterDescription.getPredicateForJavadoc()).isEqualTo("is rookie"); assertThat(getterDescription.getNegativePredicateForJavadoc()).isEqualTo("is not rookie"); - getterDescription = new GetterDescription("", "wasRookie", BOOLEAN_TYPE_DESCRIPTION, EMPTY_TYPENAME_LIST); + getterDescription = new GetterDescription("rookie", PLAYER_TYPE_DESCRIPTION, Player.class.getMethod("wasRookie")); assertThat(getterDescription.getPredicateForJavadoc()).isEqualTo("was rookie"); assertThat(getterDescription.getNegativePredicateForJavadoc()).isEqualTo("was not rookie"); - getterDescription = new GetterDescription("", "shouldWin", BOOLEAN_TYPE_DESCRIPTION, EMPTY_TYPENAME_LIST); + getterDescription = new GetterDescription("win", PLAYER_TYPE_DESCRIPTION, Player.class.getMethod("shouldWin")); assertThat(getterDescription.getPredicateForJavadoc()).isEqualTo("should win"); assertThat(getterDescription.getNegativePredicateForJavadoc()).isEqualTo("should not win"); - getterDescription = new GetterDescription("", "canWin", BOOLEAN_TYPE_DESCRIPTION, EMPTY_TYPENAME_LIST); + getterDescription = new GetterDescription("win", PLAYER_TYPE_DESCRIPTION, Player.class.getMethod("canWin")); assertThat(getterDescription.getPredicateForJavadoc()).isEqualTo("can win"); assertThat(getterDescription.getNegativePredicateForJavadoc()).isEqualTo("cannot win"); - getterDescription = new GetterDescription("", "willWin", BOOLEAN_TYPE_DESCRIPTION, EMPTY_TYPENAME_LIST); + getterDescription = new GetterDescription("win", PLAYER_TYPE_DESCRIPTION, Player.class.getMethod("willWin")); assertThat(getterDescription.getPredicateForJavadoc()).isEqualTo("will win"); assertThat(getterDescription.getNegativePredicateForJavadoc()).isEqualTo("will not win"); - getterDescription = new GetterDescription("", "hasTrophy", BOOLEAN_TYPE_DESCRIPTION, EMPTY_TYPENAME_LIST); + getterDescription = new GetterDescription("trophy", PLAYER_TYPE_DESCRIPTION, Player.class.getMethod("hasTrophy")); assertThat(getterDescription.getPredicateForJavadoc()).isEqualTo("has trophy"); assertThat(getterDescription.getNegativePredicateForJavadoc()).isEqualTo("does not have trophy"); - getterDescription = new GetterDescription("", "doesNotHaveFun", BOOLEAN_TYPE_DESCRIPTION, EMPTY_TYPENAME_LIST); + getterDescription = new GetterDescription("fun", PLAYER_TYPE_DESCRIPTION, Player.class.getMethod("doesNotHaveFun")); assertThat(getterDescription.getPredicateForJavadoc()).isEqualTo("does not have fun"); assertThat(getterDescription.getNegativePredicateForJavadoc()).isEqualTo("has fun"); - getterDescription = new GetterDescription("", "cannotWin", BOOLEAN_TYPE_DESCRIPTION, EMPTY_TYPENAME_LIST); + getterDescription = new GetterDescription("win", PLAYER_TYPE_DESCRIPTION, Player.class.getMethod("cannotWin")); assertThat(getterDescription.getPredicateForJavadoc()).isEqualTo("cannot win"); assertThat(getterDescription.getNegativePredicateForJavadoc()).isEqualTo("can win"); - getterDescription = new GetterDescription("", "shouldNotPlay", BOOLEAN_TYPE_DESCRIPTION, EMPTY_TYPENAME_LIST); + getterDescription = new GetterDescription("play", PLAYER_TYPE_DESCRIPTION, Player.class.getMethod("shouldNotPlay")); assertThat(getterDescription.getPredicateForJavadoc()).isEqualTo("should not play"); assertThat(getterDescription.getNegativePredicateForJavadoc()).isEqualTo("should play"); } @Test - public void should_generate_predicate_for_error_message() { - getterDescription = new GetterDescription("rookie", "isRookie", BOOLEAN_TYPE_DESCRIPTION, EMPTY_TYPENAME_LIST); + public void should_generate_predicate_for_error_message() throws Exception { + getterDescription = new GetterDescription("rookie", PLAYER_TYPE_DESCRIPTION, Player.class.getMethod("isRookie")); assertThat(getterDescription.getPredicateForErrorMessagePart1()).isEqualTo("is rookie"); assertThat(getterDescription.getPredicateForErrorMessagePart2()).isEqualTo("is not"); - getterDescription = new GetterDescription("", "wasRookie", BOOLEAN_TYPE_DESCRIPTION, EMPTY_TYPENAME_LIST); + getterDescription = new GetterDescription("rookie", PLAYER_TYPE_DESCRIPTION, Player.class.getMethod("wasRookie")); assertThat(getterDescription.getPredicateForErrorMessagePart1()).isEqualTo("was rookie"); assertThat(getterDescription.getPredicateForErrorMessagePart2()).isEqualTo("was not"); - getterDescription = new GetterDescription("", "shouldWin", BOOLEAN_TYPE_DESCRIPTION, EMPTY_TYPENAME_LIST); + getterDescription = new GetterDescription("win", PLAYER_TYPE_DESCRIPTION, Player.class.getMethod("shouldWin")); assertThat(getterDescription.getPredicateForErrorMessagePart1()).isEqualTo("should win"); assertThat(getterDescription.getPredicateForErrorMessagePart2()).isEqualTo("should not"); - getterDescription = new GetterDescription("", "canWin", BOOLEAN_TYPE_DESCRIPTION, EMPTY_TYPENAME_LIST); + getterDescription = new GetterDescription("win", PLAYER_TYPE_DESCRIPTION, Player.class.getMethod("canWin")); assertThat(getterDescription.getPredicateForErrorMessagePart1()).isEqualTo("can win"); assertThat(getterDescription.getPredicateForErrorMessagePart2()).isEqualTo("cannot"); - getterDescription = new GetterDescription("", "willWin", BOOLEAN_TYPE_DESCRIPTION, EMPTY_TYPENAME_LIST); + getterDescription = new GetterDescription("win", PLAYER_TYPE_DESCRIPTION, Player.class.getMethod("willWin")); assertThat(getterDescription.getPredicateForErrorMessagePart1()).isEqualTo("will win"); assertThat(getterDescription.getPredicateForErrorMessagePart2()).isEqualTo("will not"); - getterDescription = new GetterDescription("", "hasTrophy", BOOLEAN_TYPE_DESCRIPTION, EMPTY_TYPENAME_LIST); + getterDescription = new GetterDescription("trophy", PLAYER_TYPE_DESCRIPTION, Player.class.getMethod("hasTrophy")); assertThat(getterDescription.getPredicateForErrorMessagePart1()).isEqualTo("has trophy"); assertThat(getterDescription.getPredicateForErrorMessagePart2()).isEqualTo("does not have"); - getterDescription = new GetterDescription("", "doesNotHaveFun", BOOLEAN_TYPE_DESCRIPTION, EMPTY_TYPENAME_LIST); + getterDescription = new GetterDescription("fun", PLAYER_TYPE_DESCRIPTION, Player.class.getMethod("doesNotHaveFun")); assertThat(getterDescription.getPredicateForErrorMessagePart1()).isEqualTo("does not have fun"); assertThat(getterDescription.getPredicateForErrorMessagePart2()).isEqualTo("has"); - getterDescription = new GetterDescription("", "cannotWin", BOOLEAN_TYPE_DESCRIPTION, EMPTY_TYPENAME_LIST); + getterDescription = new GetterDescription("win", PLAYER_TYPE_DESCRIPTION, Player.class.getMethod("cannotWin")); assertThat(getterDescription.getPredicateForErrorMessagePart1()).isEqualTo("cannot win"); assertThat(getterDescription.getPredicateForErrorMessagePart2()).isEqualTo("can"); - getterDescription = new GetterDescription("", "shouldNotPlay", BOOLEAN_TYPE_DESCRIPTION, EMPTY_TYPENAME_LIST); + getterDescription = new GetterDescription("play", PLAYER_TYPE_DESCRIPTION, Player.class.getMethod("shouldNotPlay")); assertThat(getterDescription.getPredicateForErrorMessagePart1()).isEqualTo("should not play"); assertThat(getterDescription.getPredicateForErrorMessagePart2()).isEqualTo("should"); } diff --git a/src/test/java/org/assertj/assertions/generator/description/TypeDescriptionTest.java b/src/test/java/org/assertj/assertions/generator/description/TypeDescriptionTest.java deleted file mode 100644 index 6f414fba..00000000 --- a/src/test/java/org/assertj/assertions/generator/description/TypeDescriptionTest.java +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * Copyright 2012-2015 the original author or authors. - */ -package org.assertj.assertions.generator.description; - -import static org.junit.rules.ExpectedException.none; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - - -public class TypeDescriptionTest { - - @Rule - public ExpectedException thrown = none(); - - @SuppressWarnings("unused") - @Test - public void should_throw_exception_in_constructor_call_if_typename_parameter_is_null() throws Exception { - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("typeName must not be null."); - new TypeDescription(null); - } - -} diff --git a/src/test/java/org/assertj/assertions/generator/description/TypeNameTest.java b/src/test/java/org/assertj/assertions/generator/description/TypeNameTest.java deleted file mode 100644 index 4f0b4094..00000000 --- a/src/test/java/org/assertj/assertions/generator/description/TypeNameTest.java +++ /dev/null @@ -1,283 +0,0 @@ -/** - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * Copyright 2012-2015 the original author or authors. - */ -package org.assertj.assertions.generator.description; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown; - -import org.assertj.assertions.generator.NestedClassesTest; -import org.assertj.assertions.generator.data.OuterClass; -import org.assertj.assertions.generator.data.nba.Player; -import org.junit.Rule; -import org.junit.Test; -import org.junit.experimental.theories.Theories; -import org.junit.experimental.theories.Theory; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; - -@RunWith(Theories.class) -public class TypeNameTest implements NestedClassesTest { - - @Rule - public ExpectedException thrown = ExpectedException.none(); - private TypeName typeName; - - @Test - public void should_create_valid_typename_from_class() { - typeName = new TypeName(Player.class); - assertThat(typeName.getSimpleName()).isEqualTo("Player"); - assertThat(typeName.getSimpleNameWithOuterClass()).isEqualTo("Player"); - assertThat(typeName.getSimpleNameWithOuterClassNotSeparatedByDots()).isEqualTo("Player"); - assertThat(typeName.getPackageName()).isEqualTo("org.assertj.assertions.generator.data.nba"); - assertThat(typeName.getFullyQualifiedClassName()).isEqualTo("org.assertj.assertions.generator.data.nba.Player"); - assertThat(typeName.belongsToJavaLangPackage()).isFalse(); - assertThat(typeName.isPrimitive()).isFalse(); - } - - @Theory - public void should_create_valid_typename_from_nestedclass(NestedClass nestedClass) { - typeName = new TypeName(nestedClass.getNestedClass()); - assertThat(typeName.getSimpleName()).isEqualTo(nestedClass.getNestedClass().getSimpleName()); - assertThat(typeName.getSimpleNameWithOuterClass()).isEqualTo(nestedClass.getClassNameWithOuterClass()); - assertThat(typeName.getSimpleNameWithOuterClassNotSeparatedByDots()).isEqualTo(nestedClass.getClassNameWithOuterClassNotSeparatedBytDots()); - assertThat(typeName.getOuterClassTypeName()).isEqualTo(new TypeName( - "org.assertj.assertions.generator.data.OuterClass")); - assertThat(typeName.getPackageName()).isEqualTo("org.assertj.assertions.generator.data"); - assertThat(typeName.getFullyQualifiedClassName()).isEqualTo("org.assertj.assertions.generator.data." - + nestedClass.getClassNameWithOuterClass()); - assertThat(typeName.belongsToJavaLangPackage()).isFalse(); - assertThat(typeName.isPrimitive()).isFalse(); - assertThat(typeName.isNested()).isTrue(); - } - - @Test - public void should_create_valid_typename() { - typeName = new TypeName("Player", "org.assertj.assertions.generator.data"); - assertThat(typeName.getSimpleName()).isEqualTo("Player"); - assertThat(typeName.getSimpleNameWithOuterClass()).isEqualTo("Player"); - assertThat(typeName.getSimpleNameWithOuterClassNotSeparatedByDots()).isEqualTo("Player"); - assertThat(typeName.getPackageName()).isEqualTo("org.assertj.assertions.generator.data"); - assertThat(typeName.getFullyQualifiedClassName()).isEqualTo("org.assertj.assertions.generator.data.Player"); - assertThat(typeName.belongsToJavaLangPackage()).isFalse(); - assertThat(typeName.isPrimitive()).isFalse(); - } - - @Test - public void should_create_valid_typename_from_type_name_string_description() { - typeName = new TypeName("org.assertj.assertions.generator.data.Player"); - assertThat(typeName.getSimpleName()).isEqualTo("Player"); - assertThat(typeName.getSimpleNameWithOuterClass()).isEqualTo("Player"); - assertThat(typeName.getSimpleNameWithOuterClassNotSeparatedByDots()).isEqualTo("Player"); - assertThat(typeName.getPackageName()).isEqualTo("org.assertj.assertions.generator.data"); - assertThat(typeName.belongsToJavaLangPackage()).isFalse(); - assertThat(typeName.isPrimitive()).isFalse(); - assertThat(typeName.isRealNumber()).isFalse(); - assertThat(typeName.isWholeNumber()).isFalse(); - assertThat(typeName.isNested()).isFalse(); - assertThat(typeName.getOuterClassTypeName()).isNull(); - } - - @Test - public void should_create_valid_nested_typename_from_type_name_string_description() { - typeName = new TypeName("org.assertj.assertions.generator.data.Player.Stats"); - assertThat(typeName.getSimpleName()).isEqualTo("Stats"); - assertThat(typeName.getSimpleNameWithOuterClass()).isEqualTo("Player.Stats"); - assertThat(typeName.getSimpleNameWithOuterClassNotSeparatedByDots()).isEqualTo("PlayerStats"); - assertThat(typeName.getPackageName()).isEqualTo("org.assertj.assertions.generator.data"); - assertThat(typeName.belongsToJavaLangPackage()).isFalse(); - assertThat(typeName.isPrimitive()).isFalse(); - assertThat(typeName.isRealNumber()).isFalse(); - assertThat(typeName.isWholeNumber()).isFalse(); - assertThat(typeName.isNested()).isTrue(); - assertThat(typeName.getOuterClassTypeName()).isEqualTo(new TypeName("org.assertj.assertions.generator.data.Player")); - } - - @Test - public void should_create_valid_typename_for_primitive() { - typeName = new TypeName(int.class); - assertThat(typeName.getSimpleName()).isEqualTo("int"); - assertThat(typeName.getSimpleNameWithOuterClass()).isEqualTo("int"); - assertThat(typeName.getSimpleNameWithOuterClassNotSeparatedByDots()).isEqualTo("int"); - assertThat(typeName.getPackageName()).isEmpty(); - assertThat(typeName.belongsToJavaLangPackage()).isFalse(); - assertThat(typeName.isPrimitive()).isTrue(); - } - - @Test - public void should_create_valid_typename_for_primitive_from_type_name_string_description() { - typeName = new TypeName("int"); - assertThat(typeName.getSimpleName()).isEqualTo("int"); - assertThat(typeName.getSimpleNameWithOuterClass()).isEqualTo("int"); - assertThat(typeName.getSimpleNameWithOuterClassNotSeparatedByDots()).isEqualTo("int"); - assertThat(typeName.getPackageName()).isEmpty(); - assertThat(typeName.belongsToJavaLangPackage()).isFalse(); - assertThat(typeName.isPrimitive()).isTrue(); - // same - typeName = new TypeName("int", null); - assertThat(typeName.getSimpleName()).isEqualTo("int"); - assertThat(typeName.getSimpleNameWithOuterClass()).isEqualTo("int"); - assertThat(typeName.getSimpleNameWithOuterClassNotSeparatedByDots()).isEqualTo("int"); - assertThat(typeName.getPackageName()).isEmpty(); - assertThat(typeName.belongsToJavaLangPackage()).isFalse(); - assertThat(typeName.isPrimitive()).isTrue(); - } - - @Test - public void should_fail_if_typename_description_is_empty() { - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("type name should not be blank or null"); - typeName = new TypeName(""); - } - - @Test - public void should_detect_primitives_typename() { - assertThat(new TypeName(int.class).isPrimitive()).isTrue(); - assertThat(new TypeName(long.class).isPrimitive()).isTrue(); - assertThat(new TypeName(short.class).isPrimitive()).isTrue(); - assertThat(new TypeName(boolean.class).isPrimitive()).isTrue(); - assertThat(new TypeName(char.class).isPrimitive()).isTrue(); - assertThat(new TypeName(byte.class).isPrimitive()).isTrue(); - assertThat(new TypeName(float.class).isPrimitive()).isTrue(); - assertThat(new TypeName(double.class).isPrimitive()).isTrue(); - assertThat(new TypeName(String.class).isPrimitive()).isFalse(); - assertThat(new TypeName("test.Boolean").isPrimitive()).isFalse(); - } - - @Test - public void should_detect_real_numbers_typename() { - assertThat(new TypeName(int.class).isRealNumber()).isFalse(); - assertThat(new TypeName(long.class).isRealNumber()).isFalse(); - assertThat(new TypeName(short.class).isRealNumber()).isFalse(); - assertThat(new TypeName(boolean.class).isRealNumber()).isFalse(); - assertThat(new TypeName(char.class).isRealNumber()).isFalse(); - assertThat(new TypeName(byte.class).isRealNumber()).isFalse(); - assertThat(new TypeName(float.class).isRealNumber()).isTrue(); - assertThat(new TypeName(Float.class).isRealNumber()).isTrue(); - assertThat(new TypeName(double.class).isRealNumber()).isTrue(); - assertThat(new TypeName(Double.class).isRealNumber()).isTrue(); - assertThat(new TypeName(String.class).isRealNumber()).isFalse(); - assertThat(new TypeName("test.Double").isRealNumber()).isFalse(); - } - - @Test - public void should_detect_whole_numbers_typename() { - assertThat(new TypeName(int.class).isWholeNumber()).as("int").isTrue(); - assertThat(new TypeName(Integer.class).isWholeNumber()).as("Integer").isTrue(); - assertThat(new TypeName(long.class).isWholeNumber()).as("long").isTrue(); - assertThat(new TypeName(Long.class).isWholeNumber()).as("Long").isTrue(); - assertThat(new TypeName(short.class).isWholeNumber()).as("short").isTrue(); - assertThat(new TypeName(Short.class).isWholeNumber()).as("Short").isTrue(); - assertThat(new TypeName(byte.class).isWholeNumber()).as("byte").isTrue(); - assertThat(new TypeName(Byte.class).isWholeNumber()).as("Byte").isTrue(); - assertThat(new TypeName(boolean.class).isWholeNumber()).isFalse(); - assertThat(new TypeName(char.class).isWholeNumber()).isFalse(); - assertThat(new TypeName(float.class).isWholeNumber()).isFalse(); - assertThat(new TypeName(Float.class).isWholeNumber()).isFalse(); - assertThat(new TypeName(double.class).isWholeNumber()).isFalse(); - assertThat(new TypeName(Double.class).isWholeNumber()).isFalse(); - assertThat(new TypeName(String.class).isWholeNumber()).isFalse(); - assertThat(new TypeName("test.Integer").isWholeNumber()).isFalse(); - } - - @Test - public void should_detect_boolean_typename() { - assertThat(new TypeName(boolean.class).isBoolean()).isTrue(); - assertThat(new TypeName(Boolean.class).isBoolean()).isTrue(); - assertThat(new TypeName("boolean").isBoolean()).isTrue(); - assertThat(new TypeName("Boolean").isBoolean()).isFalse(); - assertThat(new TypeName(char.class).isBoolean()).isFalse(); - } - - @Test - public void should_detect_character_typename() { - assertThat(new TypeName(char.class).isChar()).isTrue(); - assertThat(new TypeName(Character.class).isChar()).isTrue(); - assertThat(new TypeName("char").isChar()).isTrue(); - assertThat(new TypeName("Character").isChar()).isFalse(); - assertThat(new TypeName(int.class).isChar()).isFalse(); - } - - @Test - public void should_detect_primitive_wrapper_typename() { - assertThat(new TypeName(Integer.class).isPrimitiveWrapper()).as("Integer").isTrue(); - assertThat(new TypeName(Long.class).isPrimitiveWrapper()).as("Long").isTrue(); - assertThat(new TypeName(Short.class).isPrimitiveWrapper()).as("Short").isTrue(); - assertThat(new TypeName(Byte.class).isPrimitiveWrapper()).as("Byte").isTrue(); - assertThat(new TypeName(Boolean.class).isPrimitiveWrapper()).isTrue(); - assertThat(new TypeName(Character.class).isPrimitiveWrapper()).isTrue(); - assertThat(new TypeName(Float.class).isPrimitiveWrapper()).isTrue(); - assertThat(new TypeName(Double.class).isPrimitiveWrapper()).isTrue(); - assertThat(new TypeName(int.class).isPrimitiveWrapper()).as("int").isFalse(); - assertThat(new TypeName(long.class).isPrimitiveWrapper()).as("long").isFalse(); - assertThat(new TypeName(short.class).isPrimitiveWrapper()).as("short").isFalse(); - assertThat(new TypeName(byte.class).isPrimitiveWrapper()).as("byte").isFalse(); - assertThat(new TypeName(boolean.class).isPrimitiveWrapper()).isFalse(); - assertThat(new TypeName(char.class).isPrimitiveWrapper()).isFalse(); - assertThat(new TypeName(float.class).isPrimitiveWrapper()).isFalse(); - assertThat(new TypeName(double.class).isPrimitiveWrapper()).isFalse(); - assertThat(new TypeName(String.class).isPrimitiveWrapper()).isFalse(); - assertThat(new TypeName("test.Integer").isPrimitiveWrapper()).isFalse(); - } - - @Test - public void should_detect_array_typename() { - assertThat(new TypeName(String[].class).isArray()).isTrue(); - assertThat(new TypeName(int[].class).isArray()).isTrue(); - assertThat(new TypeName(int.class).isArray()).isFalse(); - assertThat(new TypeName(String.class).isArray()).isFalse(); - } - - @Test - public void should_detect_nested_typename() { - assertThat(new TypeName(String.class).isNested()).isFalse(); - assertThat(new TypeName(OuterClass.class).isNested()).isFalse(); - assertThat(new TypeName(OuterClass.InnerPerson.class).isNested()).isTrue(); - assertThat(new TypeName(OuterClass.InnerPerson.IP_InnerPerson.class).isNested()).isTrue(); - assertThat(new TypeName(OuterClass.StaticNestedPerson.class).isNested()).isTrue(); - assertThat(new TypeName(OuterClass.StaticNestedPerson.SNP_InnerPerson.class).isNested()).isTrue(); - assertThat(new TypeName(OuterClass.StaticNestedPerson.SNP_StaticNestedPerson.class).isNested()).isTrue(); - } - - @Test - public void should_fail_if_type_simple_name_is_null() { - try { - typeName = new TypeName(null, "org.assertj.assertions.generator.data"); - failBecauseExceptionWasNotThrown(IllegalArgumentException.class); - } catch (IllegalArgumentException iae) { - assertThat(iae).hasMessage("type simple name should not be null"); - } - } - - @Test - public void compare_to_should_compare_classes_fully_qualified_names() { - // compare package before all - TypeName typeNameData1A = new TypeName("A", "org.assertj.assertions.generator.data1"); - TypeName typeNameData2B = new TypeName("A", "org.assertj.assertions.generator.data2"); - assertThat(typeNameData1A.compareTo(typeNameData1A)).isZero(); - assertThat(typeNameData1A.compareTo(typeNameData2B)).isNegative(); - assertThat(typeNameData2B.compareTo(typeNameData1A)).isPositive(); - // if package are equals, compare class simple name - TypeName typeNameA = new TypeName("A", "org.assertj.assertions.generator.data"); - TypeName typeNameB = new TypeName("B", "org.assertj.assertions.generator.data"); - assertThat(typeNameA.compareTo(typeNameA)).isZero(); - assertThat(typeNameA.compareTo(typeNameB)).isNegative(); - assertThat(typeNameB.compareTo(typeNameA)).isPositive(); - } - - @Test - public void should_show_information_in_toString() { - assertThat(new TypeName("A", "org.mypackage").toString()).isEqualTo("org.mypackage.A"); - assertThat(new TypeName(int.class).toString()).isEqualTo("int"); - } - -} diff --git a/src/test/java/org/assertj/assertions/generator/description/converter/ClassToClassDescriptionConverterTest.java b/src/test/java/org/assertj/assertions/generator/description/converter/ClassToClassDescriptionConverterTest.java index a8edc4dd..aaa84052 100644 --- a/src/test/java/org/assertj/assertions/generator/description/converter/ClassToClassDescriptionConverterTest.java +++ b/src/test/java/org/assertj/assertions/generator/description/converter/ClassToClassDescriptionConverterTest.java @@ -12,12 +12,7 @@ */ package org.assertj.assertions.generator.description.converter; -import static org.assertj.core.api.Assertions.assertThat; - -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; - +import com.google.common.reflect.TypeToken; import org.assertj.assertions.generator.BeanWithExceptionsTest; import org.assertj.assertions.generator.NestedClassesTest; import org.assertj.assertions.generator.data.ArtWork; @@ -29,224 +24,283 @@ import org.assertj.assertions.generator.data.nba.PlayerAgent; import org.assertj.assertions.generator.description.ClassDescription; import org.assertj.assertions.generator.description.GetterDescription; +import org.assertj.assertions.generator.util.ClassUtil; import org.junit.BeforeClass; import org.junit.Test; import org.junit.experimental.theories.Theories; import org.junit.experimental.theories.Theory; import org.junit.runner.RunWith; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + @RunWith(Theories.class) public class ClassToClassDescriptionConverterTest implements NestedClassesTest, BeanWithExceptionsTest { - private static ClassToClassDescriptionConverter converter; - - @BeforeClass - public static void beforeAllTests() { - converter = new ClassToClassDescriptionConverter(); - } - - @Test - public void should_build_player_class_description() throws Exception { - ClassDescription classDescription = converter.convertToClassDescription(Player.class); - assertThat(classDescription.getClassName()).isEqualTo("Player"); - assertThat(classDescription.getClassNameWithOuterClass()).isEqualTo("Player"); - assertThat(classDescription.getPackageName()).isEqualTo("org.assertj.assertions.generator.data.nba"); - assertThat(classDescription.getGettersDescriptions()).hasSize(11); - } - - @Test - public void should_build_movie_class_description() throws Exception { - ClassDescription classDescription = converter.convertToClassDescription(Movie.class); - assertThat(classDescription.getClassName()).isEqualTo("Movie"); - assertThat(classDescription.getClassNameWithOuterClass()).isEqualTo("Movie"); - assertThat(classDescription.getPackageName()).isEqualTo("org.assertj.assertions.generator.data"); - assertThat(classDescription.getGettersDescriptions()).hasSize(3); - assertThat(classDescription.getFieldsDescriptions()).hasSize(4); - assertThat(classDescription.getDeclaredGettersDescriptions()).hasSize(2); - assertThat(classDescription.getDeclaredFieldsDescriptions()).hasSize(3); - assertThat(classDescription.getSuperType()).isEqualTo(ArtWork.class); - } - - @Theory - public void should_build_nestedclass_description(NestedClass nestedClass) throws Exception { - Class clazz = nestedClass.getNestedClass(); - ClassDescription classDescription = converter.convertToClassDescription(clazz); - assertThat(classDescription.getClassName()).isEqualTo(clazz.getSimpleName()); - assertThat(classDescription.getClassNameWithOuterClass()).isEqualTo(nestedClass.getClassNameWithOuterClass()); - assertThat(classDescription.getPackageName()).isEqualTo(clazz.getPackage().getName()); - assertThat(classDescription.getGettersDescriptions()).hasSize(1); - } - - @Theory - public void should_build_getter_with_exception_description(GetterWithException getter) throws Exception { - Class clazz = getter.getBeanClass(); - ClassDescription classDescription = converter.convertToClassDescription(clazz); - assertThat(classDescription.getClassName()).isEqualTo(clazz.getSimpleName()); - assertThat(classDescription.getClassNameWithOuterClass()).isEqualTo(clazz.getSimpleName()); - assertThat(classDescription.getPackageName()).isEqualTo(clazz.getPackage().getName()); - assertThat(classDescription.getGettersDescriptions()).hasSize(4); - - for (GetterDescription desc : classDescription.getGettersDescriptions()) { - if (desc.getPropertyName().equals(getter.getPropertyName())) { - assertThat(desc.getExceptions()).containsOnly(getter.getExceptions()); - break; - } - } - } - - @Test - public void should_build_class_description_for_iterable_of_primitive_type_array() throws Exception { - class Type { - List scores; - - @SuppressWarnings("unused") - public List getScores() { - return scores; - } - } - ClassDescription classDescription = converter.convertToClassDescription(Type.class); - assertThat(classDescription.getClassName()).isEqualTo("Type"); - assertThat(classDescription.getGettersDescriptions()).hasSize(1); - GetterDescription getterDescription = classDescription.getGettersDescriptions().iterator().next(); - assertThat(getterDescription.isIterableType()).as("getterDescription must be iterable").isTrue(); - assertThat(getterDescription.getElementTypeName(Type.class.getPackage().getName())).isEqualTo("int[]"); - assertThat(getterDescription.isArrayType()).as("getterDescription must not be an array").isFalse(); - } - - @Test - public void should_build_class_description_for_array_of_primitive_type_array() throws Exception { - class Type { - int[][] scores; - - @SuppressWarnings("unused") - public int[][] getScores() { - return scores; - } - } - ClassDescription classDescription = converter.convertToClassDescription(Type.class); - assertThat(classDescription.getClassName()).isEqualTo("Type"); - assertThat(classDescription.getGettersDescriptions()).hasSize(1); - GetterDescription getterDescription = classDescription.getGettersDescriptions().iterator().next(); - assertThat(getterDescription.isIterableType()).as("getterDescription is an iterable ?").isFalse(); - assertThat(getterDescription.isArrayType()).as("getterDescription is an array ?").isTrue(); - assertThat(getterDescription.getElementTypeName(Type.class.getPackage().getName())).isEqualTo("int[]"); - } - - @Test - public void should_build_class_description_for_enum_type() throws Exception { - ClassDescription classDescription = converter.convertToClassDescription(TreeEnum.class); - assertThat(classDescription.getClassName()).isEqualTo("TreeEnum"); - // should not contain getDeclaringClassGetter as we don't want to have hasDeclaringClass assertion - assertThat(classDescription.getGettersDescriptions()).hasSize(1); - GetterDescription getterDescription = classDescription.getGettersDescriptions().iterator().next(); - assertThat(getterDescription.isIterableType()).as("getterDescription must be iterable").isTrue(); - assertThat(getterDescription.getElementTypeName(TreeEnum.class.getPackage().getName())).isEqualTo("TreeEnum"); - assertThat(getterDescription.isArrayType()).as("getterDescription must be an array").isFalse(); - } - - @Test - public void should_build_class_description_for_iterable_of_Object_type() throws Exception { - // Given - class Type { - List players; - - @SuppressWarnings("unused") - public List getPlayers() { - return players; - } - } - - // When - ClassDescription classDescription = converter.convertToClassDescription(Type.class); - - // Then - assertThat(classDescription.getClassName()).isEqualTo("Type"); - assertThat(classDescription.getGettersDescriptions()).hasSize(1); - GetterDescription getterDescription = classDescription.getGettersDescriptions().iterator().next(); - assertThat(getterDescription.isIterableType()).as("getterDescription must be iterable").isTrue(); - assertThat(getterDescription.getElementTypeName(Type.class.getPackage().getName())).isEqualTo("org.assertj.assertions.generator.data.nba.Player[]"); - assertThat(getterDescription.isArrayType()).as("getterDescription is not an array").isFalse(); - } - - @Test - public void should_build_class_description_for_interface() throws Exception { - // Given an interface - // When - ClassDescription classDescription = converter.convertToClassDescription(PlayerAgent.class); - - // Then - assertThat(classDescription.getClassName()).isEqualTo("PlayerAgent"); - assertThat(classDescription.getSuperType()).isNull(); - assertThat(classDescription.getGettersDescriptions()).hasSize(1); - GetterDescription getterDescription = classDescription.getGettersDescriptions().iterator().next(); - assertThat(getterDescription.isIterableType()).as("getterDescription is not iterable").isFalse(); - assertThat(getterDescription.getPropertyName()).isEqualTo("managedPlayer"); - assertThat(getterDescription.getTypeName()).isEqualTo("Player"); - } - - @Test - public void should_build_fellowshipOfTheRing_class_description() throws Exception { - ClassDescription classDescription = converter.convertToClassDescription(FellowshipOfTheRing.class); - assertThat(classDescription.getClassName()).isEqualTo("FellowshipOfTheRing"); - assertThat(classDescription.getClassNameWithOuterClass()).isEqualTo("FellowshipOfTheRing"); - assertThat(classDescription.getClassNameWithOuterClassNotSeparatedByDots()).isEqualTo("FellowshipOfTheRing"); - assertThat(classDescription.getPackageName()).isEqualTo("org.assertj.assertions.generator.data.lotr"); - assertThat(classDescription.getGettersDescriptions()).hasSize(1); - } - - @Test - public void should_handle_toString() { - ClassDescription classDescription = converter.convertToClassDescription(FellowshipOfTheRing.class); - assertThat(classDescription.toString()).contains(FellowshipOfTheRing.class.getName()); - } - - @Test - public void should_build_class_description_for_class_with_public_fields() throws Exception { - ClassDescription classDescription = converter.convertToClassDescription(Team.class); - assertThat(classDescription.getClassName()).isEqualTo("Team"); - assertThat(classDescription.getClassNameWithOuterClass()).isEqualTo("Team"); - assertThat(classDescription.getClassNameWithOuterClassNotSeparatedByDots()).isEqualTo("Team"); - assertThat(classDescription.getPackageName()).isEqualTo("org.assertj.assertions.generator.data"); - assertThat(classDescription.getGettersDescriptions()).extracting("propertyName").containsExactly("division"); - assertThat(classDescription.getFieldsDescriptions()).extracting("name").containsOnly("name", - "oldNames", - "westCoast", - "rank", - "players", - "points", - "victoryRatio"); - } - - @Test - public void bug21_reflection_error_on_iterable_ParameterizedType() { - class MySQLException extends SQLException { - private static final long serialVersionUID = 1L; - - @SuppressWarnings("unused") - public SQLException getExceptionChain() { - return null; - } - } - ClassDescription classDescription = converter.convertToClassDescription(MySQLException.class); - // exceptionChain is a SQLException which is an Iterable but looking only at SQLException we can't deduce - // iterable type - assertThat(classDescription.getGettersDescriptions()).extracting("propertyName").contains("exceptionChain"); - } - - @Test - public void should_only_describe_overriden_getter_once() { - ClassDescription myClassDescription = converter.convertToClassDescription(ClassOverridingGetter.class); - assertThat(myClassDescription.getGettersDescriptions()).extracting("propertyName").containsOnlyOnce("myList"); - } - - public interface InterfaceWithGetter { - public abstract List getMyList(); - } - - class ClassOverridingGetter implements InterfaceWithGetter { - @Override - public ArrayList getMyList() { - return null; - } - } + private static ClassToClassDescriptionConverter converter; + + @BeforeClass + public static void beforeAllTests() { + converter = new ClassToClassDescriptionConverter(); + } + + @Test + public void should_build_player_class_description() throws Exception { + // Given + Class clazz = Player.class; + + ClassDescription classDescription = converter.convertToClassDescription(clazz); + assertThat(classDescription.getClassName()).isEqualTo(clazz.getName()); + assertThat(classDescription.getClassNameWithOuterClass()).isEqualTo(clazz.getSimpleName()); + assertThat(classDescription.getPackageName()).isEqualTo("org.assertj.assertions.generator.data.nba"); + + assertThat(classDescription.getGettersDescriptions()).hasSize(19); + } + + @Test + public void should_build_movie_class_description() throws Exception { + // Given + Class clazz = Movie.class; + + ClassDescription classDescription = converter.convertToClassDescription(clazz); + assertThat(classDescription.getClassName()).isEqualTo(clazz.getName()); + assertThat(classDescription.getClassNameWithOuterClass()).isEqualTo(clazz.getSimpleName()); + assertThat(classDescription.getPackageName()).isEqualTo("org.assertj.assertions.generator.data"); + + assertThat(classDescription.getGettersDescriptions()).hasSize(3); + assertThat(classDescription.getFieldsDescriptions()).hasSize(4); + assertThat(classDescription.getDeclaredGettersDescriptions()).hasSize(2); + assertThat(classDescription.getDeclaredFieldsDescriptions()).hasSize(3); + assertThat(classDescription.getSuperType()).isEqualTo(TypeToken.of(ArtWork.class)); + } + + @Theory + public void should_build_nestedclass_description(NestedClass nestedClass) throws Exception { + Class clazz = nestedClass.getNestedClass(); + ClassDescription classDescription = converter.convertToClassDescription(clazz); + assertThat(classDescription.getClassName()).isEqualTo(clazz.getName()); + assertThat(classDescription.getClassNameWithOuterClass()).isEqualTo(nestedClass.getClassNameWithOuterClass()); + assertThat(classDescription.getPackageName()).isEqualTo(clazz.getPackage().getName()); + assertThat(classDescription.getGettersDescriptions()).hasSize(1); + } + + @Theory + public void should_build_getter_with_exception_description(GetterWithException getter) throws Exception { + TypeToken type = getter.getBeanClass(); + Class clazz = type.getRawType(); + ClassDescription classDescription = converter.convertToClassDescription(clazz); + assertThat(classDescription.getClassName()).isEqualTo(clazz.getName()); + assertThat(classDescription.getClassNameWithOuterClass()).isEqualTo(clazz.getSimpleName()); + assertThat(classDescription.getPackageName()).isEqualTo(clazz.getPackage().getName()); + assertThat(classDescription.getGettersDescriptions()).hasSize(4); + + for (GetterDescription desc : classDescription.getGettersDescriptions()) { + if (desc.getName().equals(getter.getPropertyName())) { + assertThat(desc.getExceptions()).containsOnly(getter.getExceptions().toArray(new TypeToken[]{})); + break; + } + } + } + + class WithPrimitiveArrayCollection { + List scores; + + @SuppressWarnings("unused") + public List getScores() { + return scores; + } + } + + @Test + public void should_build_class_description_for_iterable_of_primitive_type_array() throws Exception { + // Given + Class clazz = WithPrimitiveArrayCollection.class; + + // When + ClassDescription classDescription = converter.convertToClassDescription(clazz); + assertThat(classDescription.getClassName()).isEqualTo(clazz.getName()); + assertThat(classDescription.getGettersDescriptions()).hasSize(1); + + // Then + GetterDescription getterDescription = classDescription.getGettersDescriptions().iterator().next(); + assertThat(getterDescription.isIterableType()) + .as("getterDescription must be iterable") + .isTrue(); + assertThat(getterDescription.getElementTypeName(clazz.getPackage().getName())) + .as("getterDesc must have correct element type") + .isEqualTo("int[]"); + assertThat(getterDescription.isArrayType()) + .as("getterDescription must not be an array") + .isFalse(); + } + + static class WithPrimitiveArrayArrayCollection { + int[][] scores; + + @SuppressWarnings("unused") + public int[][] getScores() { + return scores; + } + } + + @Test(expected = IllegalArgumentException.class) + public void should_fail_to_build_class_description_for_local_class() throws Exception { + class Local {} + converter.convertToClassDescription(Local.class); + } + + @Test + public void should_build_class_description_for_array_of_primitive_type_array() throws Exception { + ClassDescription classDescription = converter.convertToClassDescription(WithPrimitiveArrayArrayCollection.class); + assertThat(classDescription.getClassName()).isEqualTo(WithPrimitiveArrayArrayCollection.class.getName()); + assertThat(classDescription.getGettersDescriptions()).hasSize(1); + GetterDescription getterDescription = classDescription.getGettersDescriptions().iterator().next(); + assertThat(getterDescription.isIterableType()).as("getterDescription is an iterable ?").isFalse(); + assertThat(getterDescription.isArrayType()).as("getterDescription is an array ?").isTrue(); + assertThat(getterDescription.getElementTypeName(WithPrimitiveArrayArrayCollection.class.getPackage().getName())).isEqualTo("int[]"); + } + + @Test + public void should_build_class_description_for_enum_type() throws Exception { + ClassDescription classDescription = converter.convertToClassDescription(TreeEnum.class); + assertThat(classDescription.getClassName()).isEqualTo(TreeEnum.class.getName()); + // should not contain getDeclaringClassGetter as we don't want to have hasDeclaringClass assertion + assertThat(classDescription.getGettersDescriptions()).hasSize(1); + GetterDescription getterDescription = classDescription.getGettersDescriptions().iterator().next(); + assertThat(getterDescription.isIterableType()).as("getterDescription must be iterable").isTrue(); + assertThat(getterDescription.getElementTypeName(TreeEnum.class.getPackage().getName())) + .as("getterDescription must get the internal component type without package") + .isEqualTo(TreeEnum.class.getSimpleName()); + assertThat(getterDescription.isArrayType()).as("getterDescription must be an array").isFalse(); + } + + class WithIterableObjectType { + List players; + + @SuppressWarnings("unused") + public List getPlayers() { + return players; + } + } + + @Test + public void should_build_class_description_for_iterable_of_Object_type() throws Exception { + // Given + Class clazz = WithIterableObjectType.class; + + // When + ClassDescription classDescription = converter.convertToClassDescription(clazz); + + // Then + assertThat(classDescription.getClassName()).isEqualTo(clazz.getName()); + assertThat(classDescription.getGettersDescriptions()).hasSize(1); + GetterDescription getterDescription = classDescription.getGettersDescriptions().iterator().next(); + assertThat(getterDescription.isIterableType()) + .as("getterDescription must be iterable") + .isTrue(); + assertThat(getterDescription.getElementTypeName(WithIterableObjectType.class.getPackage().getName())) + .as("getterDesc element type must return correct array type") + .isEqualTo(ClassUtil.getTypeDeclaration(new TypeToken() {}, false, false)); + assertThat(getterDescription.isArrayType()).as("getterDescription is not an array").isFalse(); + } + + @Test + public void should_build_class_description_for_interface() throws Exception { + // Given an interface + Class clazz = PlayerAgent.class; + // When + ClassDescription classDescription = converter.convertToClassDescription(clazz); + + // Then + assertThat(classDescription.getClassName()).isEqualTo(clazz.getName()); + assertThat(classDescription.getSuperType()).isNull(); + assertThat(classDescription.getGettersDescriptions()).hasSize(1); + GetterDescription getterDescription = classDescription.getGettersDescriptions().iterator().next(); + assertThat(getterDescription.isIterableType()) + .as("getterDescription is not iterable").isFalse(); + assertThat(getterDescription.getName()) + .as("getterDesc must have correct name").isEqualTo("managedPlayer"); + assertThat(getterDescription.getTypeName(false, false)) + .as("getterDesc must have correct owning type").isEqualTo(Player.class.getSimpleName()); + assertThat(getterDescription.getTypeName(true, false)) + .as("getterDesc must have correct owning type").isEqualTo(Player.class.getName()); + } + + @Test + public void should_build_fellowshipOfTheRing_class_description() throws Exception { + // Given + Class clazz = FellowshipOfTheRing.class; + + // Then + ClassDescription classDescription = converter.convertToClassDescription(clazz); + assertThat(classDescription.getClassName()).isEqualTo(clazz.getName()); + assertThat(classDescription.getClassNameWithOuterClass()).isEqualTo("FellowshipOfTheRing"); + assertThat(classDescription.getClassNameWithOuterClassNotSeparatedByDots()).isEqualTo("FellowshipOfTheRing"); + assertThat(classDescription.getPackageName()).isEqualTo("org.assertj.assertions.generator.data.lotr"); + assertThat(classDescription.getGettersDescriptions()).hasSize(1); + } + + @Test + public void should_handle_toString() { + ClassDescription classDescription = converter.convertToClassDescription(FellowshipOfTheRing.class); + assertThat(classDescription.toString()).contains(FellowshipOfTheRing.class.getName()); + } + + @Test + public void should_build_class_description_for_class_with_public_fields() throws Exception { + // Given + Class clazz = Team.class; + + // Then + ClassDescription classDescription = converter.convertToClassDescription(clazz); + assertThat(classDescription.getClassName()).isEqualTo(clazz.getName()); + assertThat(classDescription.getClassNameWithOuterClass()).isEqualTo("Team"); + assertThat(classDescription.getClassNameWithOuterClassNotSeparatedByDots()).isEqualTo("Team"); + assertThat(classDescription.getPackageName()).isEqualTo("org.assertj.assertions.generator.data"); + assertThat(classDescription.getGettersDescriptions()).extracting("name").containsExactly("division"); + assertThat(classDescription.getFieldsDescriptions()).extracting("name").containsOnly("name", + "oldNames", + "westCoast", + "rank", + "players", + "points", + "victoryRatio"); + } + + class Bug21_SQLException extends SQLException { + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + public SQLException getExceptionChain() { + return null; + } + } + + @Test + public void bug21_reflection_error_on_iterable_ParameterizedType() { + ClassDescription classDescription = converter.convertToClassDescription(Bug21_SQLException.class); + // exceptionChain is a SQLException which is an Iterable but looking only at SQLException we can't deduce + // iterable valueType + assertThat(classDescription.getGettersDescriptions()).extracting("name").contains("exceptionChain"); + } + + @Test + public void should_only_describe_overriden_getter_once() { + ClassDescription myClassDescription = converter.convertToClassDescription(ClassOverridingGetter.class); + assertThat(myClassDescription.getGettersDescriptions()).extracting("name").containsOnlyOnce("myList"); + } + + public interface InterfaceWithGetter { + List getMyList(); + } + + class ClassOverridingGetter implements InterfaceWithGetter { + @Override + public ArrayList getMyList() { + return null; + } + } } diff --git a/src/test/java/org/assertj/assertions/generator/util/ClassUtilTest.java b/src/test/java/org/assertj/assertions/generator/util/ClassUtilTest.java index cfb8466c..f5426818 100644 --- a/src/test/java/org/assertj/assertions/generator/util/ClassUtilTest.java +++ b/src/test/java/org/assertj/assertions/generator/util/ClassUtilTest.java @@ -12,59 +12,43 @@ */ package org.assertj.assertions.generator.util; -import static org.assertj.assertions.generator.util.ClassUtil.collectClasses; -import static org.assertj.assertions.generator.util.ClassUtil.declaredGetterMethodsOf; -import static org.assertj.assertions.generator.util.ClassUtil.getClassesRelatedTo; -import static org.assertj.assertions.generator.util.ClassUtil.getNegativePredicateFor; -import static org.assertj.assertions.generator.util.ClassUtil.getPredicatePrefix; -import static org.assertj.assertions.generator.util.ClassUtil.getSimpleNameWithOuterClass; -import static org.assertj.assertions.generator.util.ClassUtil.getSimpleNameWithOuterClassNotSeparatedByDots; -import static org.assertj.assertions.generator.util.ClassUtil.getterMethodsOf; -import static org.assertj.assertions.generator.util.ClassUtil.inheritsCollectionOrIsIterable; -import static org.assertj.assertions.generator.util.ClassUtil.isPredicate; -import static org.assertj.assertions.generator.util.ClassUtil.isStandardGetter; -import static org.assertj.assertions.generator.util.ClassUtil.isValidGetterName; -import static org.assertj.assertions.generator.util.ClassUtil.propertyNameOf; -import static org.assertj.core.api.Assertions.assertThat; - -import java.lang.reflect.Method; -import java.lang.reflect.ParameterizedType; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Set; - +import com.google.common.base.Function; +import com.google.common.collect.Lists; +import com.google.common.reflect.TypeToken; +import org.assertj.assertions.generator.AssertionGeneratorTest; import org.assertj.assertions.generator.NestedClassesTest; -import org.assertj.assertions.generator.data.ArtWork; -import org.assertj.assertions.generator.data.BeanWithOneException; -import org.assertj.assertions.generator.data.BeanWithTwoExceptions; -import org.assertj.assertions.generator.data.Dollar$; -import org.assertj.assertions.generator.data.Movie; -import org.assertj.assertions.generator.data.Name; -import org.assertj.assertions.generator.data.OuterClass; -import org.assertj.assertions.generator.data.OuterClass.StaticNestedPerson; -import org.assertj.assertions.generator.data.Primitives; -import org.assertj.assertions.generator.data.Team; -import org.assertj.assertions.generator.data.TreeEnum; +import org.assertj.assertions.generator.data.*; import org.assertj.assertions.generator.data.lotr.FellowshipOfTheRing; import org.assertj.assertions.generator.data.lotr.Race; import org.assertj.assertions.generator.data.lotr.Ring; import org.assertj.assertions.generator.data.lotr.TolkienCharacter; import org.assertj.assertions.generator.data.nba.Player; import org.assertj.assertions.generator.data.nba.PlayerAgent; +import org.assertj.assertions.generator.description.GetterDescriptionTest; +import org.assertj.core.api.BooleanAssert; import org.junit.Test; import org.junit.experimental.theories.Theories; import org.junit.experimental.theories.Theory; import org.junit.runner.RunWith; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.util.*; + +import static org.assertj.assertions.generator.util.ClassUtil.*; +import static org.assertj.core.api.Assertions.assertThat; + @RunWith(Theories.class) public class ClassUtilTest implements NestedClassesTest { private static final Class[] NO_PARAMS = new Class[0]; + private static final TypeToken PLAYER_TYPE = TypeToken.of(Player.class); + @Test public void should_get_class_only() { - assertThat(collectClasses(getClass().getClassLoader(), Movie.class.getName())).containsOnly(Movie.class); + assertThat(collectClasses(getClass().getClassLoader(), Movie.class.getName())).containsOnly(TypeToken.of(Movie.class)); } @Test(expected = IllegalArgumentException.class) @@ -72,30 +56,43 @@ public void should_thow_exception_when_classLoader_null() { collectClasses((ClassLoader) null, "org.assertj.assertions.generator.data"); } + // Could easily be a method reference in Java 8 for TypeToken::of + private static final Function, TypeToken> TYPE_TOKEN_TRANSFORM = new Function, TypeToken>() { + @Override + public TypeToken apply(final Class input) { + return TypeToken.of(input); + } + }; + @Test public void should_get_classes_in_package_and_subpackages() { - Set> classesInPackage = collectClasses("org.assertj.assertions.generator.data"); - assertThat(classesInPackage).contains(Player.class, PlayerAgent.class, ArtWork.class, Name.class, Movie.class, - Movie.PublicCategory.class, Ring.class, Race.class, - FellowshipOfTheRing.class, TolkienCharacter.class, - Team.class, - Dollar$.class, - org.assertj.assertions.generator.data.nba.Team.class, - TreeEnum.class, - OuterClass.InnerPerson.IP_InnerPerson.class, - OuterClass.InnerPerson.class, - OuterClass.class, - StaticNestedPerson.SNP_InnerPerson.class, - StaticNestedPerson.class, - StaticNestedPerson.SNP_StaticNestedPerson.class, - BeanWithOneException.class, BeanWithTwoExceptions.class); + Set> classesInPackage = collectClasses("org.assertj.assertions.generator.data"); + List> classes = Arrays.asList(Player.class, PlayerAgent.class, ArtWork.class, Name.class, Movie.class, + Movie.PublicCategory.class, Ring.class, Race.class, + FellowshipOfTheRing.class, TolkienCharacter.class, + Team.class, + Dollar$.class, + org.assertj.assertions.generator.data.nba.Team.class, + TreeEnum.class, + OuterClass.InnerPerson.IP_InnerPerson.class, + OuterClass.InnerPerson.class, + OuterClass.class, + OuterClass.StaticNestedPerson.SNP_InnerPerson.class, + OuterClass.StaticNestedPerson.class, + OuterClass.StaticNestedPerson.SNP_StaticNestedPerson.class, + BeanWithOneException.class, BeanWithTwoExceptions.class); + + // Java 8? :( + assertThat(classesInPackage).containsAll(Lists.transform(classes, TYPE_TOKEN_TRANSFORM)); } @Test public void should_get_classes_with_provided_class_loader() { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - Set> classesInPackage = collectClasses(classLoader, "org.assertj.assertions.generator.data"); - assertThat(classesInPackage).contains(Player.class, ArtWork.class, Name.class, Movie.class, Ring.class, Race.class); + Set> classesInPackage = collectClasses(classLoader, "org.assertj.assertions.generator.data"); + List> classes = Arrays.asList(Player.class, ArtWork.class, Name.class, Movie.class, Ring.class, Race.class); + + assertThat(classesInPackage).containsAll(Lists.transform(classes, TYPE_TOKEN_TRANSFORM)); } @Test @@ -186,21 +183,21 @@ public void should_return_false_if_string_does_not_follow_getter_name_pattern() @Test public void should_return_getters_methods_only() throws Exception { - Set playerGetterMethods = getterMethodsOf(Player.class, Collections.>emptySet()); + Set playerGetterMethods = getterMethodsOf(PLAYER_TYPE, Collections.>emptySet()); assertThat(playerGetterMethods).contains(Player.class.getMethod("getTeam", NO_PARAMS)) .doesNotContain(Player.class.getMethod("isInTeam", String.class)); } @Test public void should_also_return_inherited_getters_methods() throws Exception { - Set playerGetterMethods = getterMethodsOf(Movie.class, Collections.>emptySet()); + Set playerGetterMethods = getterMethodsOf(TypeToken.of(Movie.class), Collections.>emptySet()); assertThat(playerGetterMethods).contains(Movie.class.getMethod("getReleaseDate", NO_PARAMS), ArtWork.class.getMethod("getTitle", NO_PARAMS)); } @Test public void should_not_return_inherited_getters_methods() throws Exception { - Set playerGetterMethods = declaredGetterMethodsOf(Movie.class, Collections.>emptySet()); + Set playerGetterMethods = declaredGetterMethodsOf(TypeToken.of(Movie.class), Collections.>emptySet()); assertThat(playerGetterMethods).contains(Movie.class.getMethod("getReleaseDate", NO_PARAMS)) .doesNotContain(ArtWork.class.getMethod("getTitle", NO_PARAMS)); } @@ -275,6 +272,181 @@ public void getClass_on_generic_should_return_Number_class() throws Exception { Class classes = ClassUtil.getClass(method.getGenericReturnType()); assertThat(classes).isEqualTo(Number.class); } + + public static class Inner {} + + @Test + public void resolve_type_name_in_package() throws Exception { + assertThat(ClassUtil.resolveTypeNameInPackage(String.class, String.class.getPackage().getName())) + .as("java lang type has simple name with package") + .isEqualTo(String.class.getSimpleName()); + assertThat(ClassUtil.resolveTypeNameInPackage(String.class, null)) + .as("java lang type has simple name without package") + .isEqualTo(String.class.getSimpleName()); + + assertThat(ClassUtil.resolveTypeNameInPackage(ClassUtilTest.class, null)) + .as("normal type has FQN without package") + .isEqualTo(ClassUtilTest.class.getName()); + assertThat(ClassUtil.resolveTypeNameInPackage(ClassUtilTest.class, ClassUtilTest.class.getPackage().getName())) + .as("normal type does not has FQN with package") + .isEqualTo(ClassUtilTest.class.getSimpleName()); + assertThat(ClassUtil.resolveTypeNameInPackage(ClassUtilTest.class, String.class.getPackage().getName())) + .as("normal type does not have FQN with other package") + .isEqualTo(ClassUtilTest.class.getName()); + + assertThat(ClassUtil.resolveTypeNameInPackage(Inner.class, null)) + .as("inner type has FQN without package") + .isEqualTo(Inner.class.getName()); + assertThat(ClassUtil.resolveTypeNameInPackage(Inner.class, Inner.class.getPackage().getName())) + .as("inner type does not have FQN with package") + .isEqualTo(String.format("%s$%s", ClassUtilTest.class.getSimpleName(), Inner.class.getSimpleName())); + } + + + @Test + public void java_lang_types_should_work_with_isJavaLangType() throws Exception { + assertThat(ClassUtil.isJavaLangType(Object.class)).isTrue(); + assertThat(ClassUtil.isJavaLangType(boolean.class)).isTrue(); + assertThat(ClassUtil.isJavaLangType(Boolean.class)).isTrue(); + + // wrong + assertThat(ClassUtil.isJavaLangType(ClassUtilTest.class)).isFalse(); + } + + @Test + public void can_properly_compute_Assert_types() throws Exception { + TypeToken thisType = TypeToken.of(ClassUtilTest.class); + + assertThat(ClassUtil.getAssertType(thisType, thisType.getRawType().getPackage().getName())) + .as("resolves non-built-in type correctly") + .isEqualTo("ClassUtilTestAssert"); + + TypeToken primitive = TypeToken.of(boolean.class); + assertThat(ClassUtil.getAssertType(primitive, thisType.getRawType().getPackage().getName())) + .as("resolves primitive correctly") + .isEqualTo(BooleanAssert.class.getName()); + + TypeToken wrapper = TypeToken.of(Boolean.class); + assertThat(ClassUtil.getAssertType(wrapper, thisType.getRawType().getPackage().getName())) + .as("resolves primitive wrapper correctly") + .isEqualTo(BooleanAssert.class.getName()); + + assertThat(ClassUtil.getAssertType(wrapper, BooleanAssert.class.getPackage().getName())) + .as("resolves package correctly for built-in package") + .isEqualTo(BooleanAssert.class.getSimpleName()); + } + + @Test + public void properly_check_if_types_are_boolean() throws Exception { + TypeToken wrapper = new TypeToken(getClass()) {}; + TypeToken primitive = TypeToken.of(boolean.class); + TypeToken neither = TypeToken.of(ClassUtilTest.class); + + assertThat(ClassUtil.isBoolean(wrapper)).as("for wrapper").isTrue(); + assertThat(ClassUtil.isBoolean(primitive)).as("for primitive").isTrue(); + assertThat(ClassUtil.isBoolean(neither)).as("for non-boolean").isFalse(); + } + + @Test + public void should_check_that_nested_packages_work() throws Exception { + + assertThat(ClassUtil.isInnerPackageOf(ClassUtilTest.class.getPackage(), + AssertionGeneratorTest.class.getPackage())) + .as("from 'super' package") + .isTrue(); + + assertThat(ClassUtil.isInnerPackageOf(ClassUtilTest.class.getPackage(), + ClassUtilTest.class.getPackage())) + .as("same package") + .isTrue(); + + assertThat(ClassUtil.isInnerPackageOf(ClassUtilTest.class.getPackage(), + GetterDescriptionTest.class.getPackage())) + .as("sibling package") + .isFalse(); + + } + + @SuppressWarnings("unused") + static class Foo { + List listOfT; + List> listOfFooString; + List[]> listOfFooIntArr; + List[]> listOfFooIntArrArrArr; + Class clazz; + Class> clazzFoo; + } + + @Test + public void create_generic_type_declaration() throws Exception { + TypeToken> fooInteger = new TypeToken>(getClass()) {}; + String result = ClassUtil.getTypeDeclaration(fooInteger, false, true); + String expected = String.format("%s.%s.%s", ClassUtilTest.class.getPackage().getName(), ClassUtilTest.class.getSimpleName(), Foo.class.getSimpleName()); + assertThat(result).isEqualTo(expected); + + // nested! + TypeToken>> fooFooInteger = new TypeToken>>(getClass()){}; + result = ClassUtil.getTypeDeclaration(fooFooInteger, false, false); + expected = String.format("%s.%s<%s.%s>", ClassUtilTest.class.getSimpleName(), Foo.class.getSimpleName(), + ClassUtilTest.class.getSimpleName(), Foo.class.getSimpleName()); + assertThat(result).isEqualTo(expected); + + // check getting the field's type + Field listOfTField = Foo.class.getDeclaredField("listOfT"); + result = ClassUtil.getTypeDeclaration(fooFooInteger.resolveType(listOfTField.getGenericType()), false, false); + expected = String.format("List<%s.%s>", ClassUtilTest.class.getSimpleName(), Foo.class.getSimpleName()); + assertThat(result).isEqualTo(expected); + + result = ClassUtil.getTypeDeclaration(fooFooInteger.resolveType(listOfTField.getGenericType()), true, false); + expected = String.format("List>", ClassUtilTest.class.getSimpleName(), Foo.class.getSimpleName()); + assertThat(result).isEqualTo(expected); + + // List of non-T type + Field listOfFooStringField = Foo.class.getDeclaredField("listOfFooString"); + result = ClassUtil.getTypeDeclaration(fooInteger.resolveType(listOfFooStringField.getGenericType()), false, false); + expected = String.format("List<%s.%s>", ClassUtilTest.class.getSimpleName(), Foo.class.getSimpleName()); + assertThat(result).isEqualTo(expected); + + result = ClassUtil.getTypeDeclaration(fooInteger.resolveType(listOfFooStringField.getGenericType()), true, false); + expected = String.format("List>", ClassUtilTest.class.getSimpleName(), Foo.class.getSimpleName()); + assertThat(result).isEqualTo(expected); + + // List of Foo[] + + Field listOfFooIntArr = Foo.class.getDeclaredField("listOfFooIntArr"); + result = ClassUtil.getTypeDeclaration(fooInteger.resolveType(listOfFooIntArr.getGenericType()), false, false); + expected = String.format("List<%s.%s[]>", ClassUtilTest.class.getSimpleName(), Foo.class.getSimpleName()); + assertThat(result).isEqualTo(expected); + + // List of Foo[] + Field listOfFooIntArrArrArr = Foo.class.getDeclaredField("listOfFooIntArrArrArr"); + result = ClassUtil.getTypeDeclaration(fooInteger.resolveType(listOfFooIntArrArrArr.getGenericType()), false, false); + expected = String.format("List<%s.%s[]>", ClassUtilTest.class.getSimpleName(), Foo.class.getSimpleName()); + assertThat(result).isEqualTo(expected); + } + + + @Test + public void create_wildcard_version() throws Exception { + TypeToken> fooInteger = new TypeToken>(getClass()) {}; + Field clazz = Foo.class.getDeclaredField("clazz"); + String result = ClassUtil.getTypeDeclaration(fooInteger.resolveType(clazz.getGenericType()), false, true); + String expected = "Class"; + assertThat(result).isEqualTo(expected); + + result = ClassUtil.getTypeDeclaration(fooInteger.resolveType(clazz.getGenericType()), true, false); + assertThat(result).isEqualTo(expected); + + Field clazzFoo = Foo.class.getDeclaredField("clazzFoo"); + result = ClassUtil.getTypeDeclaration(fooInteger.resolveType(clazzFoo.getGenericType()), true, false); + expected = String.format("Class>", ClassUtilTest.class.getSimpleName(), Foo.class.getSimpleName()); + assertThat(result).isEqualTo(expected); + + result = ClassUtil.getTypeDeclaration(fooInteger.resolveType(clazzFoo.getGenericType()), false, false); + expected = String.format("Class<%s.%s>", ClassUtilTest.class.getSimpleName(), Foo.class.getSimpleName()); + assertThat(result).isEqualTo(expected); + } + private static class Generic { @SuppressWarnings("unused") diff --git a/src/test/resources/AbstractArtWorkAssert.expected.txt b/src/test/resources/AbstractArtWorkAssert.expected.txt index 19cd6893..fb69845a 100644 --- a/src/test/resources/AbstractArtWorkAssert.expected.txt +++ b/src/test/resources/AbstractArtWorkAssert.expected.txt @@ -29,7 +29,7 @@ public abstract class AbstractArtWorkAssert, A // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting publicCategory of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - + // null safe check Movie.PublicCategory actualPublicCategory = actual.getPublicCategory(); if (!Objects.areEqual(actualPublicCategory, publicCategory)) { @@ -52,7 +52,7 @@ public abstract class AbstractMovieAssert, A // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting releaseDate of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - + // null safe check java.util.Date actualReleaseDate = actual.getReleaseDate(); if (!Objects.areEqual(actualReleaseDate, releaseDate)) { @@ -75,7 +75,7 @@ public abstract class AbstractMovieAssert, A // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting producer of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - + // null safe check String actualProducer = actual.producer; if (!Objects.areEqual(actualProducer, producer)) { @@ -99,7 +99,7 @@ public abstract class AbstractMovieAssert, A // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting rating of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - // check + // check value for rating double actualRating = actual.rating; if (actualRating != rating) { failWithMessage(assertjErrorMessage, actual, rating, actualRating); @@ -123,11 +123,11 @@ public abstract class AbstractMovieAssert, A isNotNull(); double actualRating = actual.rating; - + // overrides the default error message with a more explicit one String assertjErrorMessage = String.format("\nExpecting rating:\n <%s>\nto be close to:\n <%s>\nby less than <%s> but difference was <%s>", actualRating, rating, offset, Math.abs(rating - actualRating)); - + // check Assertions.assertThat(actualRating).overridingErrorMessage(assertjErrorMessage).isCloseTo(rating, Assertions.within(offset)); @@ -144,11 +144,11 @@ public abstract class AbstractMovieAssert, A // check that actual Movie we want to make assertions on is not null. isNotNull(); - // check + // check that property call/field access is true if (!actual.xrated) { failWithMessage("\nExpecting that actual Movie is xrated but is not."); } - + // return the current assertion for method chaining return myself; } @@ -162,11 +162,11 @@ public abstract class AbstractMovieAssert, A // check that actual Movie we want to make assertions on is not null. isNotNull(); - // check + // check that property call/field access is false if (actual.xrated) { failWithMessage("\nExpecting that actual Movie is not xrated but is."); } - + // return the current assertion for method chaining return myself; } diff --git a/src/test/resources/AnnotatedClassAssert.expected.txt b/src/test/resources/AnnotatedClassAssert.expected.txt index 900bd9df..badd901b 100644 --- a/src/test/resources/AnnotatedClassAssert.expected.txt +++ b/src/test/resources/AnnotatedClassAssert.expected.txt @@ -40,7 +40,7 @@ public class AnnotatedClassAssert extends AbstractObjectAssertonly the given String elements and nothing else in whatever order. - * + * * @param arrayPropertyThrowsException the given elements that should be contained in actual BeanWithOneException's arrayPropertyThrowsException. * @return this assertion object. * @throws AssertionError if the actual BeanWithOneException's arrayPropertyThrowsException does not contain all given String elements and nothing else. @@ -65,7 +65,7 @@ public class BeanWithOneExceptionAssert extends AbstractObjectAssert 0) { failWithMessage(assertjErrorMessage, actual, java.util.Arrays.toString(actual.getArrayPropertyThrowsException())); } - + + // return the current assertion for method chaining + return this; + } + + + /** + * Verifies that the actual BeanWithOneException is boolean property throws exception. + * @return this assertion object. + * @throws AssertionError - if the actual BeanWithOneException is not boolean property throws exception. + * @throws java.io.IOException if actual.isBooleanPropertyThrowsException() throws one. + */ + public BeanWithOneExceptionAssert isBooleanPropertyThrowsException() throws java.io.IOException { + // check that actual BeanWithOneException we want to make assertions on is not null. + isNotNull(); + + // check that property call/field access is true + if (!actual.isBooleanPropertyThrowsException()) { + failWithMessage("\nExpecting that actual BeanWithOneException is boolean property throws exception but is not."); + } + + // return the current assertion for method chaining + return this; + } + + /** + * Verifies that the actual BeanWithOneException is not boolean property throws exception. + * @return this assertion object. + * @throws AssertionError - if the actual BeanWithOneException is boolean property throws exception. + * @throws java.io.IOException if actual.isBooleanPropertyThrowsException() throws one. + */ + public BeanWithOneExceptionAssert isNotBooleanPropertyThrowsException() throws java.io.IOException { + // check that actual BeanWithOneException we want to make assertions on is not null. + isNotNull(); + + // check that property call/field access is false + if (actual.isBooleanPropertyThrowsException()) { + failWithMessage("\nExpecting that actual BeanWithOneException is not boolean property throws exception but is."); + } + // return the current assertion for method chaining return this; } - /** * Verifies that the actual BeanWithOneException's iterablePropertyThrowsException contains the given String elements. @@ -131,14 +169,14 @@ public class BeanWithOneExceptionAssert extends AbstractObjectAssert { // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting wheelsCount of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - + // check int actualWheelsCount = actual.getWheelsCount(); if (actualWheelsCount != wheelsCount) { diff --git a/src/test/resources/ClassUsingDifferentClassesWithSameName.expected.txt b/src/test/resources/ClassUsingDifferentClassesWithSameName.expected.txt index 42cb6f7a..363f010b 100644 --- a/src/test/resources/ClassUsingDifferentClassesWithSameName.expected.txt +++ b/src/test/resources/ClassUsingDifferentClassesWithSameName.expected.txt @@ -40,7 +40,7 @@ public class ClassUsingDifferentClassesWithSameNameAssert extends AbstractObject // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting nbaTeam of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - + // null safe check org.assertj.assertions.generator.data.nba.Team actualNbaTeam = actual.getNbaTeam(); if (!Objects.areEqual(actualNbaTeam, nbaTeam)) { @@ -63,7 +63,7 @@ public class ClassUsingDifferentClassesWithSameNameAssert extends AbstractObject // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting team of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - + // null safe check org.assertj.assertions.generator.data.Team actualTeam = actual.getTeam(); if (!Objects.areEqual(actualTeam, team)) { diff --git a/src/test/resources/FieldPropertyClash.expected.txt b/src/test/resources/FieldPropertyClash.expected.txt index 25b9f330..da79bf4e 100644 --- a/src/test/resources/FieldPropertyClash.expected.txt +++ b/src/test/resources/FieldPropertyClash.expected.txt @@ -28,6 +28,114 @@ public class FieldPropertyClashAssert extends AbstractObjectAssertonly the given Object elements and nothing else in whatever order. - * + * * @param expectedCase the given elements that should be contained in actual Keywords's case. * @return this assertion object. * @throws AssertionError if the actual Keywords's case does not contain all given Object elements and nothing else. @@ -309,7 +309,7 @@ public class KeywordsAssert extends AbstractObjectAssert 0) { failWithMessage(assertjErrorMessage, actual, java.util.Arrays.toString(actual.getCase())); } - + // return the current assertion for method chaining return this; } - + /** * Verifies that the actual Keywords's catch is equal to the given one. @@ -372,7 +372,7 @@ public class KeywordsAssert extends AbstractObjectAssert expectedConst) { // check that actual Keywords we want to make assertions on is not null. isNotNull(); // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting const of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - + // null safe check - Class actualConst = actual.getConst(); + Class actualConst = actual.getConst(); if (!Objects.areEqual(actualConst, expectedConst)) { failWithMessage(assertjErrorMessage, actual, expectedConst, actualConst); } @@ -441,7 +477,7 @@ public class KeywordsAssert extends AbstractObjectAssert\nto be close to:\n <%s>\nby less than <%s> but difference was <%s>", actualDouble, expectedDouble, offset, Math.abs(expectedDouble - actualDouble)); - + // check Assertions.assertThat(actualDouble).overridingErrorMessage(assertjErrorMessage).isCloseTo(expectedDouble, Assertions.within(offset)); @@ -696,7 +732,7 @@ public class KeywordsAssert extends AbstractObjectAssert\nto be close to:\n <%s>\nby less than <%s> but difference was <%s>", actualFloat, expectedFloat, offset, Math.abs(expectedFloat - actualFloat)); - + // check Assertions.assertThat(actualFloat).overridingErrorMessage(assertjErrorMessage).isCloseTo(expectedFloat, Assertions.within(offset)); @@ -884,7 +920,7 @@ public class KeywordsAssert extends AbstractObjectAssertonly the given String elements and nothing else in whatever order. - * + * * @param expectedSwitch the given elements that should be contained in actual Keywords's switch. * @return this assertion object. * @throws AssertionError if the actual Keywords's switch does not contain all given String elements and nothing else. @@ -1391,7 +1427,7 @@ public class KeywordsAssert extends AbstractObjectAssert 0) { failWithMessage(assertjErrorMessage, actual, java.util.Arrays.toString(actual.getSwitch())); } - + // return the current assertion for method chaining return this; } - + /** * Verifies that the actual Keywords's synchronized is equal to the given one. @@ -1456,7 +1492,7 @@ public class KeywordsAssert extends AbstractObjectAssert { // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting publicCategory of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - + // null safe check Movie.PublicCategory actualPublicCategory = actual.getPublicCategory(); if (!Objects.areEqual(actualPublicCategory, publicCategory)) { @@ -64,7 +64,7 @@ public class MovieAssert extends AbstractObjectAssert { // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting releaseDate of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - + // null safe check java.util.Date actualReleaseDate = actual.getReleaseDate(); if (!Objects.areEqual(actualReleaseDate, releaseDate)) { @@ -87,7 +87,7 @@ public class MovieAssert extends AbstractObjectAssert { // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting title of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - + // null safe check String actualTitle = actual.getTitle(); if (!Objects.areEqual(actualTitle, title)) { @@ -110,7 +110,7 @@ public class MovieAssert extends AbstractObjectAssert { // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting creator of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - + // null safe check String actualCreator = actual.creator; if (!Objects.areEqual(actualCreator, creator)) { @@ -133,7 +133,7 @@ public class MovieAssert extends AbstractObjectAssert { // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting producer of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - + // null safe check String actualProducer = actual.producer; if (!Objects.areEqual(actualProducer, producer)) { @@ -157,7 +157,7 @@ public class MovieAssert extends AbstractObjectAssert { // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting rating of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - // check + // check value for rating double actualRating = actual.rating; if (actualRating != rating) { failWithMessage(assertjErrorMessage, actual, rating, actualRating); @@ -181,11 +181,11 @@ public class MovieAssert extends AbstractObjectAssert { isNotNull(); double actualRating = actual.rating; - + // overrides the default error message with a more explicit one String assertjErrorMessage = String.format("\nExpecting rating:\n <%s>\nto be close to:\n <%s>\nby less than <%s> but difference was <%s>", actualRating, rating, offset, Math.abs(rating - actualRating)); - + // check Assertions.assertThat(actualRating).overridingErrorMessage(assertjErrorMessage).isCloseTo(rating, Assertions.within(offset)); @@ -202,11 +202,11 @@ public class MovieAssert extends AbstractObjectAssert { // check that actual Movie we want to make assertions on is not null. isNotNull(); - // check + // check that property call/field access is true if (!actual.xrated) { failWithMessage("\nExpecting that actual Movie is xrated but is not."); } - + // return the current assertion for method chaining return this; } @@ -220,11 +220,11 @@ public class MovieAssert extends AbstractObjectAssert { // check that actual Movie we want to make assertions on is not null. isNotNull(); - // check + // check that property call/field access is false if (actual.xrated) { failWithMessage("\nExpecting that actual Movie is not xrated but is."); } - + // return the current assertion for method chaining return this; } diff --git a/src/test/resources/NestedClassAssert.hierarchical.template.expected.txt b/src/test/resources/NestedClassAssert.hierarchical.template.expected.txt index e6d6acc9..375a36ad 100644 --- a/src/test/resources/NestedClassAssert.hierarchical.template.expected.txt +++ b/src/test/resources/NestedClassAssert.hierarchical.template.expected.txt @@ -1,6 +1,5 @@ package org.assertj.assertions.generator.data; - /** * {@link ${nestedClass}} specific assertions - Generated by CustomAssertionGenerator. * diff --git a/src/test/resources/NestedClassAssert.template.expected.txt b/src/test/resources/NestedClassAssert.template.expected.txt index 9828244d..518b6d91 100644 --- a/src/test/resources/NestedClassAssert.template.expected.txt +++ b/src/test/resources/NestedClassAssert.template.expected.txt @@ -40,7 +40,7 @@ public class ${nestedClass}Assert extends AbstractObjectAssert<${nestedClass}Ass // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting name of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - + // null safe check String actualName = actual.getName(); if (!Objects.areEqual(actualName, name)) { diff --git a/src/test/resources/PlayerAgentAssert.expected.txt b/src/test/resources/PlayerAgentAssert.expected.txt index a64a647d..5b416498 100644 --- a/src/test/resources/PlayerAgentAssert.expected.txt +++ b/src/test/resources/PlayerAgentAssert.expected.txt @@ -40,7 +40,7 @@ public class PlayerAgentAssert extends AbstractObjectAssert { // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting assistsPerGame of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - + // check int actualAssistsPerGame = actual.getAssistsPerGame(); if (actualAssistsPerGame != assistsPerGame) { @@ -53,6 +53,78 @@ public class PlayerAssert extends AbstractObjectAssert { return this; } + /** + * Verifies that the actual Player is disabled. + * @return this assertion object. + * @throws AssertionError - if the actual Player is not disabled. + */ + public PlayerAssert isDisabled() { + // check that actual Player we want to make assertions on is not null. + isNotNull(); + + // check that property call/field access is true + if (!actual.isDisabled()) { + failWithMessage("\nExpecting that actual Player is disabled but is not."); + } + + // return the current assertion for method chaining + return this; + } + + /** + * Verifies that the actual Player is not disabled. + * @return this assertion object. + * @throws AssertionError - if the actual Player is disabled. + */ + public PlayerAssert isNotDisabled() { + // check that actual Player we want to make assertions on is not null. + isNotNull(); + + // check that property call/field access is false + if (actual.isDisabled()) { + failWithMessage("\nExpecting that actual Player is not disabled but is."); + } + + // return the current assertion for method chaining + return this; + } + + /** + * Verifies that the actual Player does not have fun. + * @return this assertion object. + * @throws AssertionError - if the actual Player has fun. + */ + public PlayerAssert doesNotHaveFun() { + // check that actual Player we want to make assertions on is not null. + isNotNull(); + + // check that property call/field access is true + if (!actual.doesNotHaveFun()) { + failWithMessage("\nExpecting that actual Player does not have fun but has."); + } + + // return the current assertion for method chaining + return this; + } + + /** + * Verifies that the actual Player has fun. + * @return this assertion object. + * @throws AssertionError - if the actual Player does not have fun. + */ + public PlayerAssert hasFun() { + // check that actual Player we want to make assertions on is not null. + isNotNull(); + + // check that property call/field access is false + if (actual.doesNotHaveFun()) { + failWithMessage("\nExpecting that actual Player has fun but does not have."); + } + + // return the current assertion for method chaining + return this; + } + /** * Verifies that the actual Player's name is equal to the given one. * @param name the given name to compare the actual Player's name to. @@ -65,7 +137,7 @@ public class PlayerAssert extends AbstractObjectAssert { // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting name of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - + // null safe check org.assertj.assertions.generator.data.Name actualName = actual.getName(); if (!Objects.areEqual(actualName, name)) { @@ -76,6 +148,42 @@ public class PlayerAssert extends AbstractObjectAssert { return this; } + /** + * Verifies that the actual Player should not play. + * @return this assertion object. + * @throws AssertionError - if the actual Player should play. + */ + public PlayerAssert shouldNotPlay() { + // check that actual Player we want to make assertions on is not null. + isNotNull(); + + // check that property call/field access is true + if (!actual.shouldNotPlay()) { + failWithMessage("\nExpecting that actual Player should not play but should."); + } + + // return the current assertion for method chaining + return this; + } + + /** + * Verifies that the actual Player should play. + * @return this assertion object. + * @throws AssertionError - if the actual Player should not play. + */ + public PlayerAssert shouldPlay() { + // check that actual Player we want to make assertions on is not null. + isNotNull(); + + // check that property call/field access is false + if (actual.shouldNotPlay()) { + failWithMessage("\nExpecting that actual Player should play but should not."); + } + + // return the current assertion for method chaining + return this; + } + /** * Verifies that the actual Player's points contains the given int[] elements. * @param points the given elements that should be contained in actual Player's points. @@ -88,14 +196,14 @@ public class PlayerAssert extends AbstractObjectAssert { // check that given int[] varargs is not null. if (points == null) failWithMessage("Expecting points parameter not to be null."); - + // check with standard error message, to set another message call: info.overridingErrorMessage("my error message"); Iterables.instance().assertContains(info, actual.getPoints(), points); // return the current assertion for method chaining return this; } - + /** * Verifies that the actual Player's points contains the given int[] elements in Collection. * @param points the given elements that should be contained in actual Player's points. @@ -111,7 +219,7 @@ public class PlayerAssert extends AbstractObjectAssert { failWithMessage("Expecting points parameter not to be null."); return this; // to fool Eclipse "Null pointer access" warning on toArray. } - + // check with standard error message, to set another message call: info.overridingErrorMessage("my error message"); Iterables.instance().assertContains(info, actual.getPoints(), points.toArray()); @@ -131,7 +239,7 @@ public class PlayerAssert extends AbstractObjectAssert { // check that given int[] varargs is not null. if (points == null) failWithMessage("Expecting points parameter not to be null."); - + // check with standard error message, to set another message call: info.overridingErrorMessage("my error message"); Iterables.instance().assertContainsOnly(info, actual.getPoints(), points); @@ -154,7 +262,7 @@ public class PlayerAssert extends AbstractObjectAssert { failWithMessage("Expecting points parameter not to be null."); return this; // to fool Eclipse "Null pointer access" warning on toArray. } - + // check with standard error message, to set another message call: info.overridingErrorMessage("my error message"); Iterables.instance().assertContainsOnly(info, actual.getPoints(), points.toArray()); @@ -175,7 +283,7 @@ public class PlayerAssert extends AbstractObjectAssert { // check that given int[] varargs is not null. if (points == null) failWithMessage("Expecting points parameter not to be null."); - + // check with standard error message (use overridingErrorMessage before contains to set your own message). Iterables.instance().assertDoesNotContain(info, actual.getPoints(), points); @@ -199,7 +307,7 @@ public class PlayerAssert extends AbstractObjectAssert { failWithMessage("Expecting points parameter not to be null."); return this; // to fool Eclipse "Null pointer access" warning on toArray. } - + // check with standard error message (use overridingErrorMessage before contains to set your own message). Iterables.instance().assertDoesNotContain(info, actual.getPoints(), points.toArray()); @@ -218,16 +326,16 @@ public class PlayerAssert extends AbstractObjectAssert { // we override the default error message with a more explicit one String assertjErrorMessage = "\nExpecting :\n <%s>\nnot to have points but had :\n <%s>"; - + // check if (actual.getPoints().iterator().hasNext()) { failWithMessage(assertjErrorMessage, actual, actual.getPoints()); } - + // return the current assertion for method chaining return this; } - + /** * Verifies that the actual Player's pointsPerGame is equal to the given one. @@ -241,7 +349,7 @@ public class PlayerAssert extends AbstractObjectAssert { // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting pointsPerGame of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - + // check int actualPointsPerGame = actual.getPointsPerGame(); if (actualPointsPerGame != pointsPerGame) { @@ -264,7 +372,7 @@ public class PlayerAssert extends AbstractObjectAssert { // check that given String varargs is not null. if (previousTeams == null) failWithMessage("Expecting previousTeams parameter not to be null."); - + // check with standard error message (use overridingErrorMessage before contains to set your own message). Assertions.assertThat(actual.getPreviousTeams()).contains(previousTeams); @@ -274,7 +382,7 @@ public class PlayerAssert extends AbstractObjectAssert { /** * Verifies that the actual Player's previousTeams contains only the given String elements and nothing else in whatever order. - * + * * @param previousTeams the given elements that should be contained in actual Player's previousTeams. * @return this assertion object. * @throws AssertionError if the actual Player's previousTeams does not contain all given String elements and nothing else. @@ -285,7 +393,7 @@ public class PlayerAssert extends AbstractObjectAssert { // check that given String varargs is not null. if (previousTeams == null) failWithMessage("Expecting previousTeams parameter not to be null."); - + // check with standard error message (use overridingErrorMessage before contains to set your own message). Assertions.assertThat(actual.getPreviousTeams()).containsOnly(previousTeams); @@ -306,7 +414,7 @@ public class PlayerAssert extends AbstractObjectAssert { // check that given String varargs is not null. if (previousTeams == null) failWithMessage("Expecting previousTeams parameter not to be null."); - + // check with standard error message (use overridingErrorMessage before contains to set your own message). Assertions.assertThat(actual.getPreviousTeams()).doesNotContain(previousTeams); @@ -325,16 +433,16 @@ public class PlayerAssert extends AbstractObjectAssert { // we override the default error message with a more explicit one String assertjErrorMessage = "\nExpecting :\n <%s>\nnot to have previousTeams but had :\n <%s>"; - - // check + + // check that it is not empty if (actual.getPreviousTeams().length > 0) { failWithMessage(assertjErrorMessage, actual, java.util.Arrays.toString(actual.getPreviousTeams())); } - + // return the current assertion for method chaining return this; } - + /** * Verifies that the actual Player's reboundsPerGame is equal to the given one. @@ -348,7 +456,7 @@ public class PlayerAssert extends AbstractObjectAssert { // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting reboundsPerGame of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - + // check int actualReboundsPerGame = actual.getReboundsPerGame(); if (actualReboundsPerGame != reboundsPerGame) { @@ -359,6 +467,78 @@ public class PlayerAssert extends AbstractObjectAssert { return this; } + /** + * Verifies that the actual Player is rookie. + * @return this assertion object. + * @throws AssertionError - if the actual Player is not rookie. + */ + public PlayerAssert isRookie() { + // check that actual Player we want to make assertions on is not null. + isNotNull(); + + // check that property call/field access is true + if (!actual.isRookie()) { + failWithMessage("\nExpecting that actual Player is rookie but is not."); + } + + // return the current assertion for method chaining + return this; + } + + /** + * Verifies that the actual Player is not rookie. + * @return this assertion object. + * @throws AssertionError - if the actual Player is rookie. + */ + public PlayerAssert isNotRookie() { + // check that actual Player we want to make assertions on is not null. + isNotNull(); + + // check that property call/field access is false + if (actual.isRookie()) { + failWithMessage("\nExpecting that actual Player is not rookie but is."); + } + + // return the current assertion for method chaining + return this; + } + + /** + * Verifies that the actual Player was rookie. + * @return this assertion object. + * @throws AssertionError - if the actual Player was not rookie. + */ + public PlayerAssert wasRookie() { + // check that actual Player we want to make assertions on is not null. + isNotNull(); + + // check that property call/field access is true + if (!actual.wasRookie()) { + failWithMessage("\nExpecting that actual Player was rookie but was not."); + } + + // return the current assertion for method chaining + return this; + } + + /** + * Verifies that the actual Player was not rookie. + * @return this assertion object. + * @throws AssertionError - if the actual Player was rookie. + */ + public PlayerAssert wasNotRookie() { + // check that actual Player we want to make assertions on is not null. + isNotNull(); + + // check that property call/field access is false + if (actual.wasRookie()) { + failWithMessage("\nExpecting that actual Player was not rookie but was."); + } + + // return the current assertion for method chaining + return this; + } + /** * Verifies that the actual Player's size is equal to the given one. * @param size the given size to compare the actual Player's size to. @@ -372,7 +552,7 @@ public class PlayerAssert extends AbstractObjectAssert { // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting size of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - // check + // check value for size float actualSize = actual.getSize(); if (actualSize != size) { failWithMessage(assertjErrorMessage, actual, size, actualSize); @@ -396,11 +576,11 @@ public class PlayerAssert extends AbstractObjectAssert { isNotNull(); float actualSize = actual.getSize(); - + // overrides the default error message with a more explicit one String assertjErrorMessage = String.format("\nExpecting size:\n <%s>\nto be close to:\n <%s>\nby less than <%s> but difference was <%s>", actualSize, size, offset, Math.abs(size - actualSize)); - + // check Assertions.assertThat(actualSize).overridingErrorMessage(assertjErrorMessage).isCloseTo(size, Assertions.within(offset)); @@ -420,7 +600,7 @@ public class PlayerAssert extends AbstractObjectAssert { // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting team of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - + // null safe check String actualTeam = actual.getTeam(); if (!Objects.areEqual(actualTeam, team)) { @@ -443,14 +623,14 @@ public class PlayerAssert extends AbstractObjectAssert { // check that given Player varargs is not null. if (teamMates == null) failWithMessage("Expecting teamMates parameter not to be null."); - + // check with standard error message, to set another message call: info.overridingErrorMessage("my error message"); Iterables.instance().assertContains(info, actual.getTeamMates(), teamMates); // return the current assertion for method chaining return this; } - + /** * Verifies that the actual Player's teamMates contains the given Player elements in Collection. * @param teamMates the given elements that should be contained in actual Player's teamMates. @@ -466,7 +646,7 @@ public class PlayerAssert extends AbstractObjectAssert { failWithMessage("Expecting teamMates parameter not to be null."); return this; // to fool Eclipse "Null pointer access" warning on toArray. } - + // check with standard error message, to set another message call: info.overridingErrorMessage("my error message"); Iterables.instance().assertContains(info, actual.getTeamMates(), teamMates.toArray()); @@ -486,7 +666,7 @@ public class PlayerAssert extends AbstractObjectAssert { // check that given Player varargs is not null. if (teamMates == null) failWithMessage("Expecting teamMates parameter not to be null."); - + // check with standard error message, to set another message call: info.overridingErrorMessage("my error message"); Iterables.instance().assertContainsOnly(info, actual.getTeamMates(), teamMates); @@ -509,7 +689,7 @@ public class PlayerAssert extends AbstractObjectAssert { failWithMessage("Expecting teamMates parameter not to be null."); return this; // to fool Eclipse "Null pointer access" warning on toArray. } - + // check with standard error message, to set another message call: info.overridingErrorMessage("my error message"); Iterables.instance().assertContainsOnly(info, actual.getTeamMates(), teamMates.toArray()); @@ -530,7 +710,7 @@ public class PlayerAssert extends AbstractObjectAssert { // check that given Player varargs is not null. if (teamMates == null) failWithMessage("Expecting teamMates parameter not to be null."); - + // check with standard error message (use overridingErrorMessage before contains to set your own message). Iterables.instance().assertDoesNotContain(info, actual.getTeamMates(), teamMates); @@ -554,7 +734,7 @@ public class PlayerAssert extends AbstractObjectAssert { failWithMessage("Expecting teamMates parameter not to be null."); return this; // to fool Eclipse "Null pointer access" warning on toArray. } - + // check with standard error message (use overridingErrorMessage before contains to set your own message). Iterables.instance().assertDoesNotContain(info, actual.getTeamMates(), teamMates.toArray()); @@ -573,85 +753,157 @@ public class PlayerAssert extends AbstractObjectAssert { // we override the default error message with a more explicit one String assertjErrorMessage = "\nExpecting :\n <%s>\nnot to have teamMates but had :\n <%s>"; - + // check if (actual.getTeamMates().iterator().hasNext()) { failWithMessage(assertjErrorMessage, actual, actual.getTeamMates()); } - + // return the current assertion for method chaining return this; } - + /** - * Verifies that the actual Player is disabled. + * Verifies that the actual Player has trophy. * @return this assertion object. - * @throws AssertionError - if the actual Player is not disabled. + * @throws AssertionError - if the actual Player does not have trophy. */ - public PlayerAssert isDisabled() { + public PlayerAssert hasTrophy() { // check that actual Player we want to make assertions on is not null. isNotNull(); - // check - if (!actual.isDisabled()) { - failWithMessage("\nExpecting that actual Player is disabled but is not."); + // check that property call/field access is true + if (!actual.hasTrophy()) { + failWithMessage("\nExpecting that actual Player has trophy but does not have."); } - + // return the current assertion for method chaining return this; } /** - * Verifies that the actual Player is not disabled. + * Verifies that the actual Player does not have trophy. * @return this assertion object. - * @throws AssertionError - if the actual Player is disabled. + * @throws AssertionError - if the actual Player has trophy. */ - public PlayerAssert isNotDisabled() { + public PlayerAssert doesNotHaveTrophy() { // check that actual Player we want to make assertions on is not null. isNotNull(); - // check - if (actual.isDisabled()) { - failWithMessage("\nExpecting that actual Player is not disabled but is."); + // check that property call/field access is false + if (actual.hasTrophy()) { + failWithMessage("\nExpecting that actual Player does not have trophy but has."); } - + // return the current assertion for method chaining return this; } /** - * Verifies that the actual Player is rookie. + * Verifies that the actual Player can win. * @return this assertion object. - * @throws AssertionError - if the actual Player is not rookie. + * @throws AssertionError - if the actual Player cannot win. */ - public PlayerAssert isRookie() { + public PlayerAssert canWin() { // check that actual Player we want to make assertions on is not null. isNotNull(); // check - if (!actual.isRookie()) { - failWithMessage("\nExpecting that actual Player is rookie but is not."); + if (!actual.canWin()) { + failWithMessage("\nExpecting that actual Player can win but cannot."); } - + // return the current assertion for method chaining return this; } /** - * Verifies that the actual Player is not rookie. + * Verifies that the actual Player cannot win. * @return this assertion object. - * @throws AssertionError - if the actual Player is rookie. + * @throws AssertionError - if the actual Player can win. */ - public PlayerAssert isNotRookie() { + public PlayerAssert cannotWin() { // check that actual Player we want to make assertions on is not null. isNotNull(); // check - if (actual.isRookie()) { - failWithMessage("\nExpecting that actual Player is not rookie but is."); + if (!actual.cannotWin()) { + failWithMessage("\nExpecting that actual Player cannot win but can."); + } + + // return the current assertion for method chaining + return this; + } + + /** + * Verifies that the actual Player should win. + * @return this assertion object. + * @throws AssertionError - if the actual Player should not win. + */ + public PlayerAssert shouldWin() { + // check that actual Player we want to make assertions on is not null. + isNotNull(); + + // check that property call/field access is true + if (!actual.shouldWin()) { + failWithMessage("\nExpecting that actual Player should win but should not."); + } + + // return the current assertion for method chaining + return this; + } + + /** + * Verifies that the actual Player should not win. + * @return this assertion object. + * @throws AssertionError - if the actual Player should win. + */ + public PlayerAssert shouldNotWin() { + // check that actual Player we want to make assertions on is not null. + isNotNull(); + + // check that property call/field access is false + if (actual.shouldWin()) { + failWithMessage("\nExpecting that actual Player should not win but should."); } - + + // return the current assertion for method chaining + return this; + } + + /** + * Verifies that the actual Player will win. + * @return this assertion object. + * @throws AssertionError - if the actual Player will not win. + */ + public PlayerAssert willWin() { + // check that actual Player we want to make assertions on is not null. + isNotNull(); + + // check that property call/field access is true + if (!actual.willWin()) { + failWithMessage("\nExpecting that actual Player will win but will not."); + } + + // return the current assertion for method chaining + return this; + } + + /** + * Verifies that the actual Player will not win. + * @return this assertion object. + * @throws AssertionError - if the actual Player will win. + */ + public PlayerAssert willNotWin() { + // check that actual Player we want to make assertions on is not null. + isNotNull(); + + // check that property call/field access is false + if (actual.willWin()) { + failWithMessage("\nExpecting that actual Player will not win but will."); + } + // return the current assertion for method chaining return this; } diff --git a/src/test/resources/PrimitivesAssert.expected.txt b/src/test/resources/PrimitivesAssert.expected.txt index 4c31c4e3..759e6152 100644 --- a/src/test/resources/PrimitivesAssert.expected.txt +++ b/src/test/resources/PrimitivesAssert.expected.txt @@ -29,6 +29,78 @@ public class PrimitivesAssert extends AbstractObjectAssert\nto be close to:\n <%s>\nby less than <%s> but difference was <%s>", actualDouble, expectedDouble, offset, Math.abs(expectedDouble - actualDouble)); - + // check Assertions.assertThat(actualDouble).overridingErrorMessage(assertjErrorMessage).isCloseTo(expectedDouble, Assertions.within(offset)); @@ -207,11 +279,11 @@ public class PrimitivesAssert extends AbstractObjectAssert\nto be close to:\n <%s>\nby less than <%s> but difference was <%s>", actualDoubleWrapper, doubleWrapper, offset, Math.abs(doubleWrapper - actualDoubleWrapper)); - + // check Assertions.assertThat(actualDoubleWrapper).overridingErrorMessage(assertjErrorMessage).isCloseTo(doubleWrapper, Assertions.within(offset)); @@ -219,6 +291,42 @@ public class PrimitivesAssert extends AbstractObjectAssert\nto be close to:\n <%s>\nby less than <%s> but difference was <%s>", actualFloat, expectedFloat, offset, Math.abs(expectedFloat - actualFloat)); - + // check Assertions.assertThat(actualFloat).overridingErrorMessage(assertjErrorMessage).isCloseTo(expectedFloat, Assertions.within(offset)); @@ -305,11 +413,11 @@ public class PrimitivesAssert extends AbstractObjectAssert\nto be close to:\n <%s>\nby less than <%s> but difference was <%s>", actualFloatWrapper, floatWrapper, offset, Math.abs(floatWrapper - actualFloatWrapper)); - + // check Assertions.assertThat(actualFloatWrapper).overridingErrorMessage(assertjErrorMessage).isCloseTo(floatWrapper, Assertions.within(offset)); @@ -329,7 +437,7 @@ public class PrimitivesAssert extends AbstractObjectAssert { // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting division of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - + // null safe check String actualDivision = actual.getDivision(); if (!Objects.areEqual(actualDivision, division)) { @@ -65,7 +65,7 @@ public class TeamAssert extends AbstractObjectAssert { // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting name of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - + // null safe check String actualName = actual.name; if (!Objects.areEqual(actualName, name)) { @@ -88,7 +88,7 @@ public class TeamAssert extends AbstractObjectAssert { // check that given String varargs is not null. if (oldNames == null) failWithMessage("Expecting oldNames parameter not to be null."); - + // check with standard error message (use overridingErrorMessage before contains to set your own message). Assertions.assertThat(actual.oldNames).contains(oldNames); @@ -98,7 +98,7 @@ public class TeamAssert extends AbstractObjectAssert { /** * Verifies that the actual Team's oldNames contains only the given String elements and nothing else in whatever order. - * + * * @param oldNames the given elements that should be contained in actual Team's oldNames. * @return this assertion object. * @throws AssertionError if the actual Team's oldNames does not contain all given String elements and nothing else. @@ -109,7 +109,7 @@ public class TeamAssert extends AbstractObjectAssert { // check that given String varargs is not null. if (oldNames == null) failWithMessage("Expecting oldNames parameter not to be null."); - + // check with standard error message (use overridingErrorMessage before contains to set your own message). Assertions.assertThat(actual.oldNames).containsOnly(oldNames); @@ -130,7 +130,7 @@ public class TeamAssert extends AbstractObjectAssert { // check that given String varargs is not null. if (oldNames == null) failWithMessage("Expecting oldNames parameter not to be null."); - + // check with standard error message (use overridingErrorMessage before contains to set your own message). Assertions.assertThat(actual.oldNames).doesNotContain(oldNames); @@ -149,16 +149,16 @@ public class TeamAssert extends AbstractObjectAssert { // we override the default error message with a more explicit one String assertjErrorMessage = "\nExpecting :\n <%s>\nnot to have oldNames but had :\n <%s>"; - - // check + + // check that it is not empty if (actual.oldNames.length > 0) { failWithMessage(assertjErrorMessage, actual, java.util.Arrays.toString(actual.oldNames)); } - + // return the current assertion for method chaining return this; } - + /** * Verifies that the actual Team's players contains the given org.assertj.assertions.generator.data.nba.Player elements. @@ -172,14 +172,14 @@ public class TeamAssert extends AbstractObjectAssert { // check that given org.assertj.assertions.generator.data.nba.Player varargs is not null. if (players == null) failWithMessage("Expecting players parameter not to be null."); - + // check with standard error message, to set another message call: info.overridingErrorMessage("my error message"); Iterables.instance().assertContains(info, actual.players, players); // return the current assertion for method chaining return this; } - + /** * Verifies that the actual Team's players contains the given org.assertj.assertions.generator.data.nba.Player elements in Collection. * @param players the given elements that should be contained in actual Team's players. @@ -195,7 +195,7 @@ public class TeamAssert extends AbstractObjectAssert { failWithMessage("Expecting players parameter not to be null."); return this; // to fool Eclipse "Null pointer access" warning on toArray. } - + // check with standard error message, to set another message call: info.overridingErrorMessage("my error message"); Iterables.instance().assertContains(info, actual.players, players.toArray()); @@ -215,7 +215,7 @@ public class TeamAssert extends AbstractObjectAssert { // check that given org.assertj.assertions.generator.data.nba.Player varargs is not null. if (players == null) failWithMessage("Expecting players parameter not to be null."); - + // check with standard error message, to set another message call: info.overridingErrorMessage("my error message"); Iterables.instance().assertContainsOnly(info, actual.players, players); @@ -238,7 +238,7 @@ public class TeamAssert extends AbstractObjectAssert { failWithMessage("Expecting players parameter not to be null."); return this; // to fool Eclipse "Null pointer access" warning on toArray. } - + // check with standard error message, to set another message call: info.overridingErrorMessage("my error message"); Iterables.instance().assertContainsOnly(info, actual.players, players.toArray()); @@ -259,7 +259,7 @@ public class TeamAssert extends AbstractObjectAssert { // check that given org.assertj.assertions.generator.data.nba.Player varargs is not null. if (players == null) failWithMessage("Expecting players parameter not to be null."); - + // check with standard error message (use overridingErrorMessage before contains to set your own message). Iterables.instance().assertDoesNotContain(info, actual.players, players); @@ -283,7 +283,7 @@ public class TeamAssert extends AbstractObjectAssert { failWithMessage("Expecting players parameter not to be null."); return this; // to fool Eclipse "Null pointer access" warning on toArray. } - + // check with standard error message (use overridingErrorMessage before contains to set your own message). Iterables.instance().assertDoesNotContain(info, actual.players, players.toArray()); @@ -302,16 +302,16 @@ public class TeamAssert extends AbstractObjectAssert { // we override the default error message with a more explicit one String assertjErrorMessage = "\nExpecting :\n <%s>\nnot to have players but had :\n <%s>"; - + // check if (actual.players.iterator().hasNext()) { failWithMessage(assertjErrorMessage, actual, actual.players); } - + // return the current assertion for method chaining return this; } - + /** * Verifies that the actual Team's points contains the given int[] elements. @@ -325,14 +325,14 @@ public class TeamAssert extends AbstractObjectAssert { // check that given int[] varargs is not null. if (points == null) failWithMessage("Expecting points parameter not to be null."); - + // check with standard error message, to set another message call: info.overridingErrorMessage("my error message"); Iterables.instance().assertContains(info, actual.points, points); // return the current assertion for method chaining return this; } - + /** * Verifies that the actual Team's points contains the given int[] elements in Collection. * @param points the given elements that should be contained in actual Team's points. @@ -348,7 +348,7 @@ public class TeamAssert extends AbstractObjectAssert { failWithMessage("Expecting points parameter not to be null."); return this; // to fool Eclipse "Null pointer access" warning on toArray. } - + // check with standard error message, to set another message call: info.overridingErrorMessage("my error message"); Iterables.instance().assertContains(info, actual.points, points.toArray()); @@ -368,7 +368,7 @@ public class TeamAssert extends AbstractObjectAssert { // check that given int[] varargs is not null. if (points == null) failWithMessage("Expecting points parameter not to be null."); - + // check with standard error message, to set another message call: info.overridingErrorMessage("my error message"); Iterables.instance().assertContainsOnly(info, actual.points, points); @@ -391,7 +391,7 @@ public class TeamAssert extends AbstractObjectAssert { failWithMessage("Expecting points parameter not to be null."); return this; // to fool Eclipse "Null pointer access" warning on toArray. } - + // check with standard error message, to set another message call: info.overridingErrorMessage("my error message"); Iterables.instance().assertContainsOnly(info, actual.points, points.toArray()); @@ -412,7 +412,7 @@ public class TeamAssert extends AbstractObjectAssert { // check that given int[] varargs is not null. if (points == null) failWithMessage("Expecting points parameter not to be null."); - + // check with standard error message (use overridingErrorMessage before contains to set your own message). Iterables.instance().assertDoesNotContain(info, actual.points, points); @@ -436,7 +436,7 @@ public class TeamAssert extends AbstractObjectAssert { failWithMessage("Expecting points parameter not to be null."); return this; // to fool Eclipse "Null pointer access" warning on toArray. } - + // check with standard error message (use overridingErrorMessage before contains to set your own message). Iterables.instance().assertDoesNotContain(info, actual.points, points.toArray()); @@ -455,16 +455,16 @@ public class TeamAssert extends AbstractObjectAssert { // we override the default error message with a more explicit one String assertjErrorMessage = "\nExpecting :\n <%s>\nnot to have points but had :\n <%s>"; - + // check if (actual.points.iterator().hasNext()) { failWithMessage(assertjErrorMessage, actual, actual.points); } - + // return the current assertion for method chaining return this; } - + /** * Verifies that the actual Team's rank is equal to the given one. @@ -478,7 +478,7 @@ public class TeamAssert extends AbstractObjectAssert { // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting rank of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - + // check int actualRank = actual.rank; if (actualRank != rank) { @@ -502,7 +502,7 @@ public class TeamAssert extends AbstractObjectAssert { // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting victoryRatio of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - // check + // check value for victoryRatio double actualVictoryRatio = actual.victoryRatio; if (actualVictoryRatio != victoryRatio) { failWithMessage(assertjErrorMessage, actual, victoryRatio, actualVictoryRatio); @@ -526,11 +526,11 @@ public class TeamAssert extends AbstractObjectAssert { isNotNull(); double actualVictoryRatio = actual.victoryRatio; - + // overrides the default error message with a more explicit one String assertjErrorMessage = String.format("\nExpecting victoryRatio:\n <%s>\nto be close to:\n <%s>\nby less than <%s> but difference was <%s>", actualVictoryRatio, victoryRatio, offset, Math.abs(victoryRatio - actualVictoryRatio)); - + // check Assertions.assertThat(actualVictoryRatio).overridingErrorMessage(assertjErrorMessage).isCloseTo(victoryRatio, Assertions.within(offset)); @@ -547,11 +547,11 @@ public class TeamAssert extends AbstractObjectAssert { // check that actual Team we want to make assertions on is not null. isNotNull(); - // check + // check that property call/field access is true if (!actual.westCoast) { failWithMessage("\nExpecting that actual Team is westCoast but is not."); } - + // return the current assertion for method chaining return this; } @@ -565,11 +565,11 @@ public class TeamAssert extends AbstractObjectAssert { // check that actual Team we want to make assertions on is not null. isNotNull(); - // check + // check that property call/field access is false if (actual.westCoast) { failWithMessage("\nExpecting that actual Team is not westCoast but is."); } - + // return the current assertion for method chaining return this; } diff --git a/src/test/resources/customtemplates/custom_has_assertion_template_for_whole_number.txt b/src/test/resources/customtemplates/custom_has_assertion_template_for_whole_number.txt index f79a1301..79603821 100644 --- a/src/test/resources/customtemplates/custom_has_assertion_template_for_whole_number.txt +++ b/src/test/resources/customtemplates/custom_has_assertion_template_for_whole_number.txt @@ -13,7 +13,7 @@ // overrides the default error message with a more explicit one String assertjErrorMessage = "\nExpecting ${property} of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>"; - + // check ${propertyType} actual${Property} = actual.get${Property}(); if (actual${Property} != ${property_safe}) {