Skip to content

Commit

Permalink
Implement InnerClassAssert for easy inner class testing
Browse files Browse the repository at this point in the history
  • Loading branch information
Philzen committed Jun 13, 2024
1 parent 3abe251 commit aac2514
Show file tree
Hide file tree
Showing 4 changed files with 240 additions and 132 deletions.
Original file line number Diff line number Diff line change
@@ -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<ACTUAL extends AbstractMethodAssert<ACTUAL>> extends AbstractAssert<AbstractMethodAssert<ACTUAL>, 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;
}
}
Original file line number Diff line number Diff line change
@@ -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<InnerClassAssert, ClassOrInterfaceDeclaration> {

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<MethodDeclaration> 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<MethodAssert> {

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<MethodAnnotationAssert> {

private final MethodAssert parent;

protected MethodAnnotationAssert(MethodAssert methodAssert, List<AnnotationExpr> annotationExpr) {
super(annotationExpr);
parent = methodAssert;
}

public InnerClassAssert toInnerClassAssert() {
return parent.innerClassAssert;
}

public MethodAssert toMethod() {
return parent;
}
}
}
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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<JavaFileAssert, CompilationUnit> {

Expand Down Expand Up @@ -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<ClassOrInterfaceDeclaration> 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> constructorDeclaration = actual.getType(0).getConstructorByParameterTypes(paramTypes);
Expand Down Expand Up @@ -178,5 +189,4 @@ public JavaFileAssert fileDoesNotContains(final String... lines) {
public TypeAnnotationAssert assertTypeAnnotations() {
return new TypeAnnotationAssert(this, actual.getType(0).getAnnotations());
}

}
Loading

0 comments on commit aac2514

Please sign in to comment.