Skip to content

Commit

Permalink
Add tests for internal apis
Browse files Browse the repository at this point in the history
  • Loading branch information
mnhock authored and mnhock committed Oct 20, 2024
1 parent 8af2ad7 commit e1871a5
Show file tree
Hide file tree
Showing 6 changed files with 382 additions and 3 deletions.
12 changes: 12 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,24 @@
<version>${junit-jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit-jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>com.tngtech.archunit</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public void check(JavaMethod method, ConditionEvents events) {
*
* @return an architectural condition for checking public except static fields
*/
public static ArchCondition<JavaField> notBePublicButNotStatic() {
public static ArchCondition<JavaField> notBePublicUnlessStatic() {
return new ArchCondition<>("not be public") {
@Override
public void check(JavaField field, ConditionEvents events) {
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/com/enofex/taikai/java/JavaConfigurer.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import static com.enofex.taikai.TaikaiRule.Configuration.defaultConfiguration;
import static com.enofex.taikai.internal.ArchConditions.hasFieldModifiers;
import static com.enofex.taikai.internal.ArchConditions.notBePublicButNotStatic;
import static com.enofex.taikai.internal.ArchConditions.notBePublicUnlessStatic;
import static com.enofex.taikai.internal.DescribedPredicates.annotatedWithAll;
import static com.enofex.taikai.internal.DescribedPredicates.areFinal;
import static com.enofex.taikai.java.Deprecations.notUseDeprecatedAPIs;
Expand Down Expand Up @@ -354,7 +354,7 @@ public JavaConfigurer fieldsShouldNotBePublic() {

public JavaConfigurer fieldsShouldNotBePublic(Configuration configuration) {
return addRule(TaikaiRule.of(fields()
.should(notBePublicButNotStatic())
.should(notBePublicUnlessStatic())
.as("Fields should not be public unless they are static"), configuration));
}

Expand Down
135 changes: 135 additions & 0 deletions src/test/java/com/enofex/taikai/internal/ArchConditionsTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package com.enofex.taikai.internal;


import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import com.tngtech.archunit.core.domain.JavaClass;
import com.tngtech.archunit.core.domain.JavaField;
import com.tngtech.archunit.core.domain.JavaMethod;
import com.tngtech.archunit.core.domain.JavaModifier;
import com.tngtech.archunit.core.domain.ThrowsClause;
import com.tngtech.archunit.lang.ConditionEvents;
import com.tngtech.archunit.lang.SimpleConditionEvent;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Set;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
class ArchConditionsTest {

@Mock
private JavaMethod mockMethod;
@Mock
private JavaField mockField;
@Mock
private JavaClass mockClass;
@Mock
private ConditionEvents events;
@Mock
private ThrowsClause mockThrowsClause;


@Test
void shouldNotDeclareThrownExceptions() {
when(this.mockMethod.getThrowsClause()).thenReturn(this.mockThrowsClause);
when(this.mockThrowsClause.isEmpty()).thenReturn(true);

ArchConditions.notDeclareThrownExceptions().check(this.mockMethod, this.events);

verify(this.events, never()).add(any(SimpleConditionEvent.class));
}

@Test
void shouldDeclareThrownExceptions() {
when(this.mockMethod.getThrowsClause()).thenReturn(this.mockThrowsClause);
when(this.mockThrowsClause.isEmpty()).thenReturn(false);

ArchConditions.notDeclareThrownExceptions().check(this.mockMethod, this.events);

verify(this.events).add(any(SimpleConditionEvent.class));
}

@Test
void shouldBePublicButNotStatic() {
when(this.mockField.getName()).thenReturn("publicField");
when(this.mockField.getOwner()).thenReturn(this.mockClass);
when(this.mockField.getModifiers()).thenReturn(EnumSet.of(JavaModifier.PUBLIC));

ArchConditions.notBePublicUnlessStatic().check(this.mockField, this.events);

ArgumentCaptor<SimpleConditionEvent> eventCaptor = ArgumentCaptor.forClass(
SimpleConditionEvent.class);
verify(this.events).add(eventCaptor.capture());
assertEquals("Field %s in class %s is public".formatted(
this.mockField.getName(), this.mockClass.getFullName()),
eventCaptor.getValue().getDescriptionLines().getFirst());
}


@Test
void shouldHaveRequiredModifiers() {
Set<JavaModifier> requiredModifiers = EnumSet.of(JavaModifier.PRIVATE, JavaModifier.FINAL);
when(this.mockField.getModifiers()).thenReturn(requiredModifiers);

ArchConditions.hasFieldModifiers(requiredModifiers).check(this.mockField, this.events);

verify(this.events, never()).add(any(SimpleConditionEvent.class));
}

@Test
void shouldNotHaveRequiredModifiers() {
Set<JavaModifier> requiredModifiers = EnumSet.of(JavaModifier.PRIVATE, JavaModifier.FINAL);
when(this.mockField.getModifiers()).thenReturn(EnumSet.of(JavaModifier.PUBLIC));
when(this.mockField.getName()).thenReturn("field");
when(this.mockField.getOwner()).thenReturn(this.mockClass);

ArchConditions.hasFieldModifiers(requiredModifiers).check(this.mockField, this.events);

ArgumentCaptor<SimpleConditionEvent> eventCaptor = ArgumentCaptor.forClass(
SimpleConditionEvent.class);
verify(this.events).add(eventCaptor.capture());
assertEquals("Field %s in class %s is missing one of this %s modifier".formatted(
this.mockField.getName(),
this.mockClass.getFullName(),
"PRIVATE, FINAL"),
eventCaptor.getValue().getDescriptionLines().getFirst());
}

@Test
void shouldHaveFieldOfType() {
String typeName = "com.example.MyType";
JavaClass mockRawType = mock(JavaClass.class);

when(mockRawType.getName()).thenReturn(typeName);
when(this.mockField.getRawType()).thenReturn(mockRawType);
when(this.mockClass.getAllFields()).thenReturn(Collections.singleton(this.mockField));

ArchConditions.haveFieldOfType(typeName).check(this.mockClass, this.events);

verify(this.events, never()).add(any(SimpleConditionEvent.class));
}

@Test
void shouldNotHaveFieldOfType() {
String typeName = "com.example.MyType";
JavaClass mockRawType = mock(JavaClass.class);

when(mockRawType.getName()).thenReturn("com.example.AnotherType");
when(this.mockField.getRawType()).thenReturn(mockRawType);
when(this.mockClass.getAllFields()).thenReturn(Collections.singleton(this.mockField));

ArchConditions.haveFieldOfType(typeName).check(this.mockClass, this.events);

verify(this.events).add(any(SimpleConditionEvent.class));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package com.enofex.taikai.internal;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.when;

import com.tngtech.archunit.core.domain.JavaClass;
import com.tngtech.archunit.core.domain.properties.CanBeAnnotated;
import java.util.Collections;
import java.util.Set;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
class DescribedPredicatesTest {

@Mock
private CanBeAnnotated canBeAnnotated;
@Mock
private JavaClass javaClass;

@Test
void shouldReturnTrueWhenAnnotatedWithSpecificAnnotation() {
String annotation = "MyAnnotation";
when(this.canBeAnnotated.isAnnotatedWith(annotation)).thenReturn(true);

assertTrue(DescribedPredicates.annotatedWith(annotation, false).test(this.canBeAnnotated));
}

@Test
void shouldReturnFalseWhenNotAnnotatedWithSpecificAnnotation() {
String annotation = "MyAnnotation";
when(this.canBeAnnotated.isAnnotatedWith(annotation)).thenReturn(false);

assertFalse(DescribedPredicates.annotatedWith(annotation, false).test(this.canBeAnnotated));
}

@Test
void shouldReturnTrueWhenAnnotatedWithAllAnnotations() {
Set<String> annotations = Set.of("MyAnnotation1", "MyAnnotation2");

when(this.canBeAnnotated.isAnnotatedWith("MyAnnotation1")).thenReturn(true);
when(this.canBeAnnotated.isAnnotatedWith("MyAnnotation2")).thenReturn(true);

assertTrue(DescribedPredicates.annotatedWithAll(annotations, false).test(this.canBeAnnotated));
}

@Test
void shouldReturnFalseWhenNotAnnotatedWithAllAnnotations() {
Set<String> annotations = Set.of("MyAnnotation1", "MyAnnotation2");

when(this.canBeAnnotated.isAnnotatedWith("MyAnnotation1")).thenReturn(false);
when(this.canBeAnnotated.isAnnotatedWith("MyAnnotation2")).thenReturn(true);

assertFalse(DescribedPredicates.annotatedWithAll(annotations, false).test(this.canBeAnnotated));
}

@Test
void shouldReturnTrueWhenClassIsFinal() {
when(this.javaClass.getModifiers()).thenReturn(
Set.of(com.tngtech.archunit.core.domain.JavaModifier.FINAL));

assertTrue(DescribedPredicates.areFinal().test(this.javaClass));
}

@Test
void shouldReturnFalseWhenClassIsNotFinal() {
when(this.javaClass.getModifiers()).thenReturn(Collections.emptySet());

assertFalse(DescribedPredicates.areFinal().test(this.javaClass));
}
}
Loading

0 comments on commit e1871a5

Please sign in to comment.