如果您想为您的 Fluent API 以 fluent 风格编写基于反射的测试(参见 Lance Java's answer),您可以使用标记接口标记您的 fluent API 类并使用 AssertJ custom assertions:
标记界面:
package myfluentapi;
interface MyFluentAPI {
// marker interface for testing
}
class Job implements MyFluentAPI {
DoAfterFirst doFirst() { /* ... */ }
}
interface DoAfterFirst extends MyFluentAPI {
FinishWith doAfterFirst();
}
interface FinishWith extends MyFluentAPI {
void thisOne();
void orThisOne();
}
测试代码:
import static myfluentapi.MyFluentAPIAssert.*;
public class JobTest {
@Test
public void doAfterFirstHasOnlyTwoChoices() {
assertThat(new Job().doFirst().doAfterFirst())
.hasOnlyChoices("thisOne", "orThisOne");
}
}
自定义断言类:
请注意,我使用 Java 8 Streams API 来比较实际方法和预期方法的列表,但如果您对功能风格。
import org.assertj.core.api.AbstractAssert;
public class MyFluentAPIAssert extends AbstractAssert<MyFluentAPIAssert, MyFluentAPI> {
protected MyFluentAPIAssert(MyFluentAPI actual) {
super(actual, MyFluentAPIAssert.class);
}
public static MyFluentAPIAssert assertThat(MyFluentAPI actual) {
return new MyFluentAPIAssert(actual);
}
private Stream<String> getActualChoices() {
return Arrays.asList(actual.getClass().getMethods()).stream()
.filter((m) -> !Object.class.equals(m.getDeclaringClass()))
.map(Method::getName);
}
public void hasChoices(String... choices) {
Stream<String> actualChoices = getActualChoices();
Stream<String> expectedChoices = Arrays.asList(choices).stream();
Set<String> actualSet = actualChoices.collect(Collectors.toSet());
String missing = expectedChoices
.filter((choice) -> !actualSet.contains(choice))
.collect(Collectors.joining(", "));
if (!missing.isEmpty()) {
failWithMessage("Expected <%s> to have choices <%s>, but the following choices were missing: <%s>", actual.getClass().getName(), String.join(", ", choices), missing);
}
}
public void hasOnlyChoices(String... choices) {
hasChoices(choices); // first fail if any are missing
Stream<String> actualChoices = getActualChoices();
Stream<String> expectedChoices = Arrays.asList(choices).stream();
Set<String> expectedSet = expectedChoices.collect(Collectors.toSet());
String extra = actualChoices
.filter((choice) -> !expectedSet.contains(choice))
.collect(Collectors.joining(", "));
if (!extra.isEmpty()) {
failWithMessage("Expected <%s> to only have choices <%s>, but found the following additional choices: <%s>", actual.getClass().getName(), String.join(", ", choices), extra);
}
}
}