From aac25140d13decd754a5c7b2582068144ed146c8 Mon Sep 17 00:00:00 2001 From: Philzen Date: Thu, 13 Jun 2024 18:32:04 +0200 Subject: [PATCH] Implement InnerClassAssert for easy inner class testing --- .../java/assertions/AbstractMethodAssert.java | 134 ++++++++++++++++++ .../java/assertions/InnerClassAssert.java | 77 ++++++++++ .../java/assertions/JavaFileAssert.java | 38 +++-- .../codegen/java/assertions/MethodAssert.java | 123 +--------------- 4 files changed, 240 insertions(+), 132 deletions(-) create mode 100644 modules/openapi-generator/src/test/java/org/openapitools/codegen/java/assertions/AbstractMethodAssert.java create mode 100644 modules/openapi-generator/src/test/java/org/openapitools/codegen/java/assertions/InnerClassAssert.java diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/assertions/AbstractMethodAssert.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/assertions/AbstractMethodAssert.java new file mode 100644 index 0000000000000..8e086291a8ef6 --- /dev/null +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/assertions/AbstractMethodAssert.java @@ -0,0 +1,134 @@ +package org.openapitools.codegen.java.assertions; + +import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; +import com.github.javaparser.ast.body.MethodDeclaration; +import com.github.javaparser.ast.nodeTypes.NodeWithName; +import org.assertj.core.api.AbstractAssert; +import org.assertj.core.api.Assertions; +import org.assertj.core.util.CanIgnoreReturnValue; + +import java.util.Arrays; +import java.util.stream.Collectors; + +@CanIgnoreReturnValue +public abstract class AbstractMethodAssert> extends AbstractAssert, MethodDeclaration> { + + protected final String methodSignature; + + protected AbstractMethodAssert(MethodDeclaration methodDeclaration, Class selfType) { + super(methodDeclaration, selfType); + this.methodSignature = methodDeclaration.getDeclarationAsString(); + } + + public abstract JavaFileAssert toFileAssert(); + public abstract AbstractAnnotationAssert assertMethodAnnotations(); + + public ACTUAL hasReturnType(final String returnType) { + Assertions.assertThat(actual.getType().toString()) + .isEqualTo(returnType); + return myself(); + } + + public ACTUAL doesNotHaveParameter(final String paramName) { + Assertions.assertThat(actual.getParameterByName(paramName)) + .withFailMessage("Method %s shouldn't have parameter %s, but it does", methodSignature, paramName) + .isEmpty(); + return myself(); + } + + public ACTUAL doesNotHaveParameters() { + Assertions.assertThat(actual.getParameters()) + .withFailMessage("Method %s shouldn't have parameter, but it does", methodSignature) + .isEmpty(); + return myself(); + } + + public ACTUAL bodyContainsLines(final String... lines) { + Assertions.assertThat(isWithImplementation()) + .withFailMessage("Method %s is abstract", methodSignature) + .isTrue(); + final String actualBody = actual.getTokenRange() + .orElseThrow(() -> new IllegalStateException("Not-abstract method doesn't have body")) + .toString(); + Assertions.assertThat(actualBody) + .withFailMessage( + "Method's %s body should contains lines\n====\n%s\n====\nbut actually was\n====\n%s\n====", + methodSignature, Arrays.stream(lines).collect(Collectors.joining(System.lineSeparator())), actualBody + ) + .contains(lines); + + return myself(); + } + + public ACTUAL bodyNotContainsLines(final String... lines) { + Assertions.assertThat(isWithImplementation()) + .withFailMessage("Method %s is abstract", methodSignature) + .isTrue(); + final String actualBody = actual.getTokenRange() + .orElseThrow(() -> new IllegalStateException("Not-abstract method doesn't have body")) + .toString(); + Assertions.assertThat(actualBody) + .withFailMessage( + "Method's %s body shouldn't contains lines\n====\n%s\n====\nbut actually was\n====\n%s\n====", + methodSignature, Arrays.stream(lines).collect(Collectors.joining(System.lineSeparator())), actualBody + ) + .doesNotContain(lines); + + return myself(); + } + + public ACTUAL doesNotHaveImplementation() { + Assertions.assertThat(isWithImplementation()) + .withFailMessage("Method %s should be abstract", methodSignature) + .isFalse(); + return myself(); + } + + public ACTUAL doesNotHaveComment() { + Assertions.assertThat(actual.getJavadocComment()) + .withFailMessage("Method %s shouldn't contains comment, but it does", methodSignature) + .isEmpty(); + return myself(); + } + + public ACTUAL commentContainsLines(final String... lines) { + Assertions.assertThat(actual.getJavadocComment()) + .withFailMessage("Method %s should contains comment, but it doesn't", methodSignature) + .isPresent(); + final String actualComment = actual.getJavadocComment().get().getContent(); + Assertions.assertThat(actualComment) + .withFailMessage( + "Method's %s comment should contains lines\n====\n%s\n====\nbut actually was\n====%s\n====", + methodSignature, Arrays.stream(lines).collect(Collectors.joining(System.lineSeparator())), actualComment + ) + .contains(lines); + + return myself(); + } + + public ACTUAL noneOfParameterHasAnnotation(final String annotationName) { + actual.getParameters() + .forEach( + param -> Assertions.assertThat(param.getAnnotations()) + .withFailMessage("Parameter %s contains annotation %s while it shouldn't", param.getNameAsString(), annotationName) + .extracting(NodeWithName::getNameAsString) + .doesNotContain(annotationName) + ); + + return myself(); + } + + private boolean isWithImplementation() { + final boolean isInterface = actual.getParentNode() + .filter(ClassOrInterfaceDeclaration.class::isInstance) + .map(ClassOrInterfaceDeclaration.class::cast) + .map(ClassOrInterfaceDeclaration::isInterface) + .orElse(false); + return !(actual.isAbstract() || (isInterface && !actual.isDefault())); + } + + @SuppressWarnings("unchecked") + private ACTUAL myself() { + return (ACTUAL) this; + } +} diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/assertions/InnerClassAssert.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/assertions/InnerClassAssert.java new file mode 100644 index 0000000000000..bf77b23925a12 --- /dev/null +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/assertions/InnerClassAssert.java @@ -0,0 +1,77 @@ +package org.openapitools.codegen.java.assertions; + +import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; +import com.github.javaparser.ast.body.MethodDeclaration; +import com.github.javaparser.ast.expr.AnnotationExpr; +import org.assertj.core.api.AbstractAssert; + +import java.util.List; +import java.util.Optional; + +public class InnerClassAssert extends AbstractAssert { + + private final JavaFileAssert parent; + private final ClassOrInterfaceDeclaration innerClass; + + protected InnerClassAssert(final JavaFileAssert fileAssert, final ClassOrInterfaceDeclaration bodyDeclaration) { + super(bodyDeclaration, InnerClassAssert.class); + parent = fileAssert; + innerClass = bodyDeclaration; + } + + public JavaFileAssert toFileAssert() { + return parent; + } + + public MethodAssert assertMethod(final String methodName, final String... paramTypes) { + Optional methods = innerClass.getChildNodes().stream() + .filter(node -> node instanceof MethodDeclaration) + .map(node -> (MethodDeclaration) node) + .filter(method -> method.getNameAsString().equals(methodName)) + .findFirst(); + + // TODO assert exists + + return new MethodAssert(this, methods.get()); + } + + public static class MethodAssert extends AbstractMethodAssert { + + private final InnerClassAssert innerClassAssert; + + MethodAssert(InnerClassAssert innerClassAssert, MethodDeclaration methodDeclaration) { + super(methodDeclaration, MethodAssert.class); + this.innerClassAssert = innerClassAssert; + } + + public MethodAnnotationAssert assertMethodAnnotations() { + return new MethodAnnotationAssert(this, actual.getAnnotations()); + } + + public InnerClassAssert toInnerClassAssert() { + return innerClassAssert; + } + + public JavaFileAssert toFileAssert() { + return innerClassAssert.toFileAssert(); + } + } + + public static class MethodAnnotationAssert extends AbstractAnnotationAssert { + + private final MethodAssert parent; + + protected MethodAnnotationAssert(MethodAssert methodAssert, List annotationExpr) { + super(annotationExpr); + parent = methodAssert; + } + + public InnerClassAssert toInnerClassAssert() { + return parent.innerClassAssert; + } + + public MethodAssert toMethod() { + return parent; + } + } +} diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/assertions/JavaFileAssert.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/assertions/JavaFileAssert.java index 007eb2c40e9a3..dd364cbdd4a72 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/assertions/JavaFileAssert.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/assertions/JavaFileAssert.java @@ -1,5 +1,14 @@ package org.openapitools.codegen.java.assertions; +import com.github.javaparser.StaticJavaParser; +import com.github.javaparser.ast.CompilationUnit; +import com.github.javaparser.ast.body.*; +import com.github.javaparser.ast.nodeTypes.NodeWithName; +import com.github.javaparser.ast.nodeTypes.modifiers.NodeWithAbstractModifier; +import org.assertj.core.api.AbstractAssert; +import org.assertj.core.api.Assertions; +import org.assertj.core.util.CanIgnoreReturnValue; + import java.io.File; import java.io.IOException; import java.nio.file.Path; @@ -8,19 +17,6 @@ import java.util.Optional; import java.util.stream.Collectors; -import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; -import com.github.javaparser.ast.body.ConstructorDeclaration; -import org.assertj.core.api.AbstractAssert; -import org.assertj.core.api.Assertions; -import org.assertj.core.util.CanIgnoreReturnValue; - -import com.github.javaparser.StaticJavaParser; -import com.github.javaparser.ast.CompilationUnit; -import com.github.javaparser.ast.body.FieldDeclaration; -import com.github.javaparser.ast.body.MethodDeclaration; -import com.github.javaparser.ast.nodeTypes.NodeWithName; -import com.github.javaparser.ast.nodeTypes.modifiers.NodeWithAbstractModifier; - @CanIgnoreReturnValue public class JavaFileAssert extends AbstractAssert { @@ -98,6 +94,21 @@ public MethodAssert assertMethod(final String methodName, final String... paramT return new MethodAssert(this, methods.get(0)); } + + @SuppressWarnings("OptionalGetWithoutIsPresent") + public InnerClassAssert findInnerClassMethod(final String className) { + Optional innerClass = actual.getType(0).getMembers().stream() + .filter(BodyDeclaration::isClassOrInterfaceDeclaration) + .map(clazz -> (ClassOrInterfaceDeclaration) clazz) + .filter(clazz -> clazz.isInnerClass() || clazz.isStatic() && clazz.getNameAsString().equals(className)) + .findFirst(); + + Assertions.assertThat(innerClass) + .withFailMessage("No inner class with name %s found", className) + .isPresent(); + + return new InnerClassAssert(this, innerClass.get ()); + } public ConstructorAssert assertConstructor(final String... paramTypes) { Optional constructorDeclaration = actual.getType(0).getConstructorByParameterTypes(paramTypes); @@ -178,5 +189,4 @@ public JavaFileAssert fileDoesNotContains(final String... lines) { public TypeAnnotationAssert assertTypeAnnotations() { return new TypeAnnotationAssert(this, actual.getType(0).getAnnotations()); } - } diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/assertions/MethodAssert.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/assertions/MethodAssert.java index cdfb564ff75aa..47150447fe209 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/assertions/MethodAssert.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/assertions/MethodAssert.java @@ -1,28 +1,19 @@ package org.openapitools.codegen.java.assertions; -import java.util.Arrays; -import java.util.Optional; -import java.util.stream.Collectors; - -import org.assertj.core.api.AbstractAssert; +import com.github.javaparser.ast.body.MethodDeclaration; +import com.github.javaparser.ast.body.Parameter; import org.assertj.core.api.Assertions; import org.assertj.core.util.CanIgnoreReturnValue; -import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; -import com.github.javaparser.ast.body.MethodDeclaration; -import com.github.javaparser.ast.body.Parameter; -import com.github.javaparser.ast.nodeTypes.NodeWithName; +import java.util.Optional; -@CanIgnoreReturnValue -public class MethodAssert extends AbstractAssert { +public class MethodAssert extends AbstractMethodAssert { private final JavaFileAssert fileAssert; - private final String methodSignature; MethodAssert(final JavaFileAssert fileAssert, final MethodDeclaration methodDeclaration) { super(methodDeclaration, MethodAssert.class); this.fileAssert = fileAssert; - this.methodSignature = methodDeclaration.getDeclarationAsString(); } public JavaFileAssert toFileAssert() { @@ -33,116 +24,12 @@ public MethodAnnotationAssert assertMethodAnnotations() { return new MethodAnnotationAssert(this, actual.getAnnotations()); } - public MethodAssert hasReturnType(final String returnType) { - Assertions.assertThat(actual.getType().toString()) - .isEqualTo(returnType); - return this; - } - public ParameterAssert hasParameter(final String paramName) { final Optional parameter = actual.getParameterByName(paramName); Assertions.assertThat(parameter) .withFailMessage("Method %s should have parameter %s, but it doesn't", methodSignature, paramName) .isPresent(); - return new ParameterAssert(this, parameter.get()); - } - - public MethodAssert doesNotHaveParameter(final String paramName) { - Assertions.assertThat(actual.getParameterByName(paramName)) - .withFailMessage("Method %s shouldn't have parameter %s, but it does", methodSignature, paramName) - .isEmpty(); - return this; - } - - public MethodAssert doesNotHaveParameters() { - Assertions.assertThat(actual.getParameters()) - .withFailMessage("Method %s shouldn't have parameter, but it does", methodSignature) - .isEmpty(); - return this; - } - - public MethodAssert bodyContainsLines(final String... lines) { - Assertions.assertThat(isWithImplementation()) - .withFailMessage("Method %s is abstract", methodSignature) - .isTrue(); - final String actualBody = actual.getTokenRange() - .orElseThrow(() -> new IllegalStateException("Not-abstract method doesn't have body")) - .toString(); - Assertions.assertThat(actualBody) - .withFailMessage( - "Method's %s body should contains lines\n====\n%s\n====\nbut actually was\n====\n%s\n====", - methodSignature, Arrays.stream(lines).collect(Collectors.joining(System.lineSeparator())), actualBody - ) - .contains(lines); - - return this; - } - - public MethodAssert bodyNotContainsLines(final String... lines) { - Assertions.assertThat(isWithImplementation()) - .withFailMessage("Method %s is abstract", methodSignature) - .isTrue(); - final String actualBody = actual.getTokenRange() - .orElseThrow(() -> new IllegalStateException("Not-abstract method doesn't have body")) - .toString(); - Assertions.assertThat(actualBody) - .withFailMessage( - "Method's %s body shouldn't contains lines\n====\n%s\n====\nbut actually was\n====\n%s\n====", - methodSignature, Arrays.stream(lines).collect(Collectors.joining(System.lineSeparator())), actualBody - ) - .doesNotContain(lines); - - return this; - } - - public MethodAssert doesNotHaveImplementation() { - Assertions.assertThat(isWithImplementation()) - .withFailMessage("Method %s should be abstract", methodSignature) - .isFalse(); - return this; - } - - public MethodAssert doesNotHaveComment() { - Assertions.assertThat(actual.getJavadocComment()) - .withFailMessage("Method %s shouldn't contains comment, but it does", methodSignature) - .isEmpty(); - return this; - } - - public MethodAssert commentContainsLines(final String... lines) { - Assertions.assertThat(actual.getJavadocComment()) - .withFailMessage("Method %s should contains comment, but it doesn't", methodSignature) - .isPresent(); - final String actualComment = actual.getJavadocComment().get().getContent(); - Assertions.assertThat(actualComment) - .withFailMessage( - "Method's %s comment should contains lines\n====\n%s\n====\nbut actually was\n====%s\n====", - methodSignature, Arrays.stream(lines).collect(Collectors.joining(System.lineSeparator())), actualComment - ) - .contains(lines); - - return this; - } - - public MethodAssert noneOfParameterHasAnnotation(final String annotationName) { - actual.getParameters() - .forEach( - param -> Assertions.assertThat(param.getAnnotations()) - .withFailMessage("Parameter %s contains annotation %s while it shouldn't", param.getNameAsString(), annotationName) - .extracting(NodeWithName::getNameAsString) - .doesNotContain(annotationName) - ); - return this; - } - - private boolean isWithImplementation() { - final boolean isInterface = actual.getParentNode() - .filter(ClassOrInterfaceDeclaration.class::isInstance) - .map(ClassOrInterfaceDeclaration.class::cast) - .map(ClassOrInterfaceDeclaration::isInterface) - .orElse(false); - return !(actual.isAbstract() || (isInterface && !actual.isDefault())); + return new ParameterAssert(this, parameter.get()); } - }