Skip to content

Commit

Permalink
Junit4-support for @ArchTest-annotated instance fields in abstract ba…
Browse files Browse the repository at this point in the history
…se class

Issue: #104

Signed-off-by: Manfred Hanke <Manfred.Hanke@tngtech.com>
  • Loading branch information
hankem committed Aug 28, 2018
1 parent c5840cc commit 1ebe38e
Show file tree
Hide file tree
Showing 7 changed files with 36 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ private static Set<ArchRuleDeclaration<?>> archRuleDeclarationsFrom(Class<?> tes
}

private static ArchRules getArchRulesIn(Field field) {
ArchRules value = getValue(field);
ArchRules value = getValue(field, field.getDeclaringClass());
return checkNotNull(value, "Field %s.%s is not initialized",
field.getDeclaringClass().getName(), field.getName());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class ArchRuleExecution extends ArchTestExecution {

@Override
Result evaluateOn(JavaClasses classes) {
ArchRule rule = getValue(ruleField);
ArchRule rule = getValue(ruleField, testClass);
try {
rule.check(classes);
} catch (Exception | AssertionError e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ boolean ignore() {
return ignore;
}

static <T> T getValue(Field field) {
return getValueOrThrowException(field, WRAP_CAUSE);
static <T> T getValue(Field field, Class<?> fieldOwner) {
return getValueOrThrowException(field, fieldOwner, WRAP_CAUSE);
}

abstract static class Result {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ private Set<ArchTestExecution> asTestExecutions(ArchRules archRules, boolean for
}

private ArchRules getArchRules(Field field) {
return getValue(field);
return getValue(field, field.getDeclaringClass());
}

private Collection<ArchTestExecution> findArchRuleMethods() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,7 @@ public void should_accept_satisfied_rule() {

runner.runChild(satisfiedRule, runNotifier);

verify(runNotifier, never()).fireTestFailure(any(Failure.class));
verify(runNotifier).fireTestFinished(descriptionCaptor.capture());
assertThat(descriptionCaptor.getValue().toString()).contains(SATISFIED_FIELD_NAME);
verifyTestFinishedSuccessfully(SATISFIED_FIELD_NAME);
}

@Test
Expand All @@ -102,11 +100,16 @@ public void should_allow_instance_fields_of_all_visibility() {

runner.runChild(ArchUnitRunnerTestUtils.getRule(PRIVATE_RULE_FIELD_NAME, runner), runNotifier);

verify(runNotifier, never()).fireTestFailure(any(Failure.class));
verify(runNotifier).fireTestFinished(descriptionCaptor.capture());
verifyTestFinishedSuccessfully(PRIVATE_RULE_FIELD_NAME);
}

assertThat(descriptionCaptor.getAllValues()).extractingResultOf("getMethodName")
.contains(PRIVATE_RULE_FIELD_NAME);
@Test
public void should_allow_instance_field_in_abstract_base_class() {
ArchUnitRunner runner = newRunnerFor(ArchTestWithAbstractBaseClass.class, cache);

runner.runChild(ArchUnitRunnerTestUtils.getRule(AbstractBaseClass.INSTANCE_FIELD_NAME, runner), runNotifier);

verifyTestFinishedSuccessfully(AbstractBaseClass.INSTANCE_FIELD_NAME);
}

@Test
Expand Down Expand Up @@ -159,6 +162,13 @@ private ArchTestExecution getRule(String name) {
return ArchUnitRunnerTestUtils.getRule(name, runner);
}

private void verifyTestFinishedSuccessfully(String expectedDescriptionMethodName) {
verify(runNotifier, never()).fireTestFailure(any(Failure.class));
verify(runNotifier).fireTestFinished(descriptionCaptor.capture());
Description description = descriptionCaptor.getValue();
assertThat(description.getMethodName()).isEqualTo(expectedDescriptionMethodName);
}

@AnalyzeClasses(packages = "some.pkg")
public static class SomeArchTest {
static final String SATISFIED_FIELD_NAME = "someSatisfiedRule";
Expand All @@ -184,6 +194,17 @@ public static class ArchTestWithPrivateInstanceField {
private ArchRule privateField = all(classes()).should(BE_SATISFIED);
}

@AnalyzeClasses(packages = "some.pkg")
public static class ArchTestWithAbstractBaseClass extends AbstractBaseClass {
}

abstract static class AbstractBaseClass {
static final String INSTANCE_FIELD_NAME = "abstractBaseClassInstanceField";

@ArchTest
ArchRule abstractBaseClassInstanceField = all(classes()).should(BE_SATISFIED);
}

@AnalyzeClasses(packages = "some.pkg")
public static class WrongArchTestWrongFieldType {
static final String NO_RULE_AT_ALL_FIELD_NAME = "noRuleAtAll";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ private static void resolveChildren(
}

private static <T> T getValue(Field field) {
return getValueOrThrowException(field, WRAP_CAUSE);
return getValueOrThrowException(field, field.getDeclaringClass(), WRAP_CAUSE);
}

private static void resolveArchRules(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,12 @@ private static <T> T getValue(Field field, Object owner) {
}
}

static <T> T getValueOrThrowException(Field field, Function<Throwable, ? extends RuntimeException> exceptionConverter) {
static <T> T getValueOrThrowException(Field field, Class<?> fieldOwner, Function<Throwable, ? extends RuntimeException> exceptionConverter) {
try {
if (Modifier.isStatic(field.getModifiers())) {
return getValue(field, null);
} else {
return getValue(field, newInstanceOf(field.getDeclaringClass()));
return getValue(field, newInstanceOf(fieldOwner));
}
} catch (ReflectionException e) {
throw exceptionConverter.apply(e.getCause());
Expand Down

0 comments on commit 1ebe38e

Please sign in to comment.