GH-1 - Update Maven artifact coordinates, package and directory structure.
Original pull request: GH-7.
This commit is contained in:
committed by
Oliver Drotbohm
parent
6c444769d7
commit
417e215993
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.acme.withatbean;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author Oliver Drotbohm
|
||||
*/
|
||||
@Configuration
|
||||
public class SampleConfiguration {
|
||||
|
||||
@Bean
|
||||
DataSource dataSource() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2020-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.acme.withatbean;
|
||||
|
||||
/**
|
||||
* @author Oliver Drotbohm
|
||||
*/
|
||||
public class TestEvents {
|
||||
|
||||
/**
|
||||
* Method calling a factory method.
|
||||
*/
|
||||
public void method() {
|
||||
JMoleculesAnnotated.of();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method calling a constructor.
|
||||
*/
|
||||
public void constructorCall() {
|
||||
new JMoleculesAnnotated();
|
||||
}
|
||||
|
||||
// jMolecules
|
||||
|
||||
@org.jmolecules.event.annotation.DomainEvent
|
||||
public static class JMoleculesAnnotated {
|
||||
public static JMoleculesAnnotated of() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static class JMoleculesImplementing implements org.jmolecules.event.types.DomainEvent {}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
@org.jmolecules.ddd.annotation.Module
|
||||
package jmolecules;
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.modulith.model;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.modulith.Modulithic;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AnnotationModulithMetadata}.
|
||||
*
|
||||
* @author Oliver Drotbohm
|
||||
*/
|
||||
class AnnotationModulithMetadataUnitTest {
|
||||
|
||||
@Test
|
||||
void findsCustomizationsOnClass() {
|
||||
|
||||
assertThat(AnnotationModulithMetadata.of(Sample.class)).hasValueSatisfying(it -> {
|
||||
assertThat(it.useFullyQualifiedModuleNames()).isTrue();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void findsCustomizationsOnClassForMetaAnnotationUsage() {
|
||||
|
||||
assertThat(AnnotationModulithMetadata.of(MetaSample.class)).hasValueSatisfying(it -> {
|
||||
assertThat(it.useFullyQualifiedModuleNames()).isTrue();
|
||||
});
|
||||
}
|
||||
|
||||
@Modulithic(useFullyQualifiedModuleNames = true)
|
||||
static class Sample {}
|
||||
|
||||
@Intermediate
|
||||
static class MetaSample {}
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Modulithic(useFullyQualifiedModuleNames = true)
|
||||
@interface Intermediate {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,258 @@
|
||||
/*
|
||||
* Copyright 2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.modulith.model;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
|
||||
import org.jmolecules.event.annotation.DomainEventHandler;
|
||||
import org.junit.jupiter.api.DynamicTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestFactory;
|
||||
import org.springframework.modulith.model.ArchitecturallyEvidentType.SpringAwareArchitecturallyEvidentType;
|
||||
import org.springframework.modulith.model.ArchitecturallyEvidentType.SpringDataAwareArchitecturallyEvidentType;
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.tngtech.archunit.core.domain.JavaClass;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ArchitecturallyEvidentType}.
|
||||
*
|
||||
* @author Oliver Drotbohm
|
||||
*/
|
||||
class ArchitecturallyEvidentTypeUnitTest {
|
||||
|
||||
Classes classes = TestUtils.getClasses();
|
||||
JavaClass self = classes.getRequiredClass(ArchitecturallyEvidentTypeUnitTest.class);
|
||||
|
||||
@Test
|
||||
void abbreviatesFullyQualifiedTypeName() {
|
||||
|
||||
ArchitecturallyEvidentType type = ArchitecturallyEvidentType.of(self, classes);
|
||||
|
||||
assertThat(type.getAbbreviatedFullName()).isEqualTo("o.s.m.m.ArchitecturallyEvidentTypeUnitTest");
|
||||
}
|
||||
|
||||
@Test
|
||||
void doesNotConsiderArbitraryTypeAStereotype() {
|
||||
|
||||
ArchitecturallyEvidentType type = ArchitecturallyEvidentType.of(self, classes);
|
||||
|
||||
assertThat(type.isEntity()).isFalse();
|
||||
assertThat(type.isAggregateRoot()).isFalse();
|
||||
assertThat(type.isRepository()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void detectsSpringAnnotatedRepositories() {
|
||||
|
||||
ArchitecturallyEvidentType type = new SpringAwareArchitecturallyEvidentType(
|
||||
classes.getRequiredClass(SpringRepository.class));
|
||||
|
||||
assertThat(type.isRepository()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void doesNotConsiderEntityAggregateRoot() {
|
||||
|
||||
ArchitecturallyEvidentType type = new SpringAwareArchitecturallyEvidentType(
|
||||
classes.getRequiredClass(SampleEntity.class));
|
||||
|
||||
assertThat(type.isEntity()).isTrue();
|
||||
assertThat(type.isAggregateRoot()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void considersEntityAnAggregateRootIfTheresARepositoryForIt() {
|
||||
|
||||
Map<Class<?>, Boolean> parameters = new HashMap<Class<?>, Boolean>();
|
||||
parameters.put(SampleEntity.class, true);
|
||||
parameters.put(OtherEntity.class, false);
|
||||
parameters.put(NoEntity.class, false);
|
||||
|
||||
parameters.entrySet().stream().forEach(it -> {
|
||||
|
||||
JavaClass entity = classes.getRequiredClass(it.getKey());
|
||||
|
||||
assertThat(new SpringDataAwareArchitecturallyEvidentType(entity, classes).isAggregateRoot())
|
||||
.isEqualTo(it.getValue());
|
||||
});
|
||||
}
|
||||
|
||||
@TestFactory
|
||||
Stream<DynamicTest> considersJMoleculesEntity() {
|
||||
|
||||
return DynamicTest.stream(getTypesFor(JMoleculesAnnotatedEntity.class, JMoleculesImplementingEntity.class), //
|
||||
it -> String.format("%s is considered an entity", it.getType().getSimpleName()), //
|
||||
it -> {
|
||||
assertThat(it.isEntity()).isTrue();
|
||||
assertThat(it.isAggregateRoot()).isFalse();
|
||||
assertThat(it.isRepository()).isFalse();
|
||||
});
|
||||
}
|
||||
|
||||
@TestFactory
|
||||
Stream<DynamicTest> considersJMoleculesAggregateRoot() {
|
||||
|
||||
return DynamicTest.stream(
|
||||
getTypesFor(JMoleculesAnnotatedAggregateRoot.class, JMoleculesImplementingAggregateRoot.class), //
|
||||
it -> String.format("%s is considered an entity, aggregate root but not a repository",
|
||||
it.getType().getSimpleName()), //
|
||||
it -> {
|
||||
assertThat(it.isEntity()).isTrue();
|
||||
assertThat(it.isAggregateRoot()).isTrue();
|
||||
assertThat(it.isRepository()).isFalse();
|
||||
});
|
||||
}
|
||||
|
||||
@TestFactory
|
||||
Stream<DynamicTest> considersJMoleculesRepository() {
|
||||
|
||||
return DynamicTest.stream(getTypesFor(JMoleculesAnnotatedRepository.class), //
|
||||
it -> String.format("%s is considered a repository", it.getType().getSimpleName()), //
|
||||
it -> {
|
||||
assertThat(it.isEntity()).isFalse();
|
||||
assertThat(it.isAggregateRoot()).isFalse();
|
||||
assertThat(it.isRepository()).isTrue();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void discoversEventsListenedToForEventListener() {
|
||||
|
||||
JavaClass listenerType = classes.getRequiredClass(SomeEventListener.class);
|
||||
|
||||
assertThat(ArchitecturallyEvidentType.of(listenerType, classes).getReferenceTypes()) //
|
||||
.extracting(JavaClass::getFullName) //
|
||||
.containsExactly(Object.class.getName(), String.class.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void discoversImplementingEventListener() {
|
||||
|
||||
JavaClass listenerType = classes.getRequiredClass(ImplementingEventListener.class);
|
||||
|
||||
assertThat(ArchitecturallyEvidentType.of(listenerType, classes).getReferenceTypes()) //
|
||||
.extracting(JavaClass::getFullName) //
|
||||
.containsExactly(ApplicationReadyEvent.class.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void discoversJMoleculesEventHandler() {
|
||||
|
||||
JavaClass type = classes.getRequiredClass(JMoleculesEventListener.class);
|
||||
|
||||
assertThat(ArchitecturallyEvidentType.of(type, classes).isEventListener()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void discoversJMoleculesRepository() {
|
||||
|
||||
JavaClass type = classes.getRequiredClass(JMoleculesImplementingRepository.class);
|
||||
|
||||
assertThat(ArchitecturallyEvidentType.of(type, classes).isRepository()).isTrue();
|
||||
}
|
||||
|
||||
private Iterator<ArchitecturallyEvidentType> getTypesFor(Class<?>... types) {
|
||||
|
||||
return Stream.of(types) //
|
||||
.map(classes::getRequiredClass) //
|
||||
.map(it -> ArchitecturallyEvidentType.of(it, classes)) //
|
||||
.iterator();
|
||||
}
|
||||
|
||||
// Spring
|
||||
|
||||
@Repository
|
||||
interface SpringRepository {}
|
||||
|
||||
@Entity
|
||||
class SampleEntity {}
|
||||
|
||||
// Spring Data
|
||||
|
||||
interface SampleRepository extends CrudRepository<SampleEntity, UUID> {}
|
||||
|
||||
@Entity
|
||||
class OtherEntity {}
|
||||
|
||||
class NoEntity {}
|
||||
|
||||
// jMolecules
|
||||
|
||||
@org.jmolecules.ddd.annotation.Entity
|
||||
class JMoleculesAnnotatedEntity {}
|
||||
|
||||
@org.jmolecules.ddd.annotation.AggregateRoot
|
||||
class JMoleculesAnnotatedAggregateRoot {}
|
||||
|
||||
class JMoleculesImplementingIdentifier implements org.jmolecules.ddd.types.Identifier {}
|
||||
|
||||
abstract class JMoleculesImplementingEntity
|
||||
implements
|
||||
org.jmolecules.ddd.types.Entity<JMoleculesImplementingAggregateRoot, JMoleculesImplementingIdentifier> {}
|
||||
|
||||
abstract class JMoleculesImplementingAggregateRoot
|
||||
implements
|
||||
org.jmolecules.ddd.types.AggregateRoot<JMoleculesImplementingAggregateRoot, JMoleculesImplementingIdentifier> {}
|
||||
|
||||
@org.jmolecules.ddd.annotation.Repository
|
||||
class JMoleculesAnnotatedRepository {}
|
||||
|
||||
interface JMoleculesEventListener {
|
||||
|
||||
@DomainEventHandler
|
||||
void on(Object event);
|
||||
}
|
||||
|
||||
interface JMoleculesImplementingRepository extends
|
||||
org.jmolecules.ddd.types.Repository<JMoleculesImplementingAggregateRoot, JMoleculesImplementingIdentifier> {}
|
||||
|
||||
// Spring
|
||||
|
||||
class SomeEventListener {
|
||||
|
||||
@EventListener
|
||||
void on(Object event) {}
|
||||
|
||||
@EventListener
|
||||
void on(String event) {}
|
||||
|
||||
@EventListener
|
||||
void onOther(Object event) {}
|
||||
}
|
||||
|
||||
class ImplementingEventListener implements ApplicationListener<ApplicationReadyEvent> {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
|
||||
*/
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationReadyEvent event) {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.modulith.model;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.modulith.model.Module.ModuleDependency;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.tngtech.archunit.core.domain.JavaClass;
|
||||
import com.tngtech.archunit.core.importer.ClassFileImporter;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ModuleDependency}.
|
||||
*
|
||||
* @author Oliver Drotbohm
|
||||
*/
|
||||
class ModuleDependencyUnitTest {
|
||||
|
||||
ClassFileImporter importer = new ClassFileImporter();
|
||||
|
||||
@Test
|
||||
public void detectsInjectionDependencies() {
|
||||
|
||||
assertThat(findDependencies(SubType.class)) //
|
||||
.containsExactlyInAnyOrder(A.class, B.class, C.class, D.class, E.class, F.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void detectsDependencyFromAnnotatedConstructor() {
|
||||
|
||||
assertThat(findDependencies(MultipleConstructors.class)) //
|
||||
.containsExactlyInAnyOrder(B.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void detectsDependencyFromSingleUnannotatedConstructor() {
|
||||
|
||||
assertThat(findDependencies(SingleConstructor.class)) //
|
||||
.containsExactlyInAnyOrder(B.class);
|
||||
}
|
||||
|
||||
private Stream<Class<?>> findDependencies(Class<?> type) {
|
||||
|
||||
return ModuleDependency.fromType(importer.importClass(type)) //
|
||||
.map(ModuleDependency::getTarget) //
|
||||
.map(JavaClass::reflect);
|
||||
}
|
||||
|
||||
static class A {}
|
||||
|
||||
static class B {}
|
||||
|
||||
static class C {}
|
||||
|
||||
static class D {}
|
||||
|
||||
static class E {}
|
||||
|
||||
static class F {}
|
||||
|
||||
static class SomeComponent {
|
||||
|
||||
@Autowired A a;
|
||||
|
||||
@Autowired
|
||||
void setD(D d) {}
|
||||
}
|
||||
|
||||
static class SubType extends SomeComponent {
|
||||
|
||||
@Autowired E e;
|
||||
|
||||
SubType(B b, C c) {}
|
||||
|
||||
@Autowired
|
||||
void setF(F f) {}
|
||||
}
|
||||
|
||||
static class MultipleConstructors {
|
||||
|
||||
MultipleConstructors(A a) {}
|
||||
|
||||
@Autowired
|
||||
MultipleConstructors(B b) {}
|
||||
}
|
||||
|
||||
static class SingleConstructor {
|
||||
SingleConstructor(B b) {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2020-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.modulith.model;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.tngtech.archunit.core.domain.JavaClasses;
|
||||
import com.tngtech.archunit.core.importer.ClassFileImporter;
|
||||
import com.tngtech.archunit.core.importer.ImportOption;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ModuleDetectionStrategy}.
|
||||
*
|
||||
* @author Oliver Drotbohm
|
||||
*/
|
||||
class ModuleDetectionStrategyUnitTest {
|
||||
|
||||
@Test
|
||||
void usesExplicitlyAnnotatedConstant() {
|
||||
|
||||
assertThat(ModuleDetectionStrategy.explictlyAnnotated())
|
||||
.isEqualTo(ModuleDetectionStrategies.EXPLICITLY_ANNOTATED);
|
||||
}
|
||||
|
||||
@Test
|
||||
void usesDirectSubPackages() {
|
||||
|
||||
assertThat(ModuleDetectionStrategy.directSubPackage())
|
||||
.isEqualTo(ModuleDetectionStrategies.DIRECT_SUB_PACKAGES);
|
||||
}
|
||||
|
||||
@Test
|
||||
void detectsJMoleculesAnnotatedModule() {
|
||||
|
||||
JavaClasses classes = new ClassFileImporter() //
|
||||
.withImportOption(new ImportOption.OnlyIncludeTests()) //
|
||||
.importPackages("jmolecules");
|
||||
|
||||
JavaPackage javaPackage = JavaPackage.of(Classes.of(classes), "jmolecules");
|
||||
|
||||
assertThat(ModuleDetectionStrategy.explictlyAnnotated().getModuleBasePackages(javaPackage))
|
||||
.containsExactly(javaPackage);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2019-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.modulith.model;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle;
|
||||
|
||||
import com.acme.withatbean.TestEvents.JMoleculesAnnotated;
|
||||
import com.acme.withatbean.TestEvents.JMoleculesImplementing;
|
||||
import com.tngtech.archunit.core.domain.JavaClass;
|
||||
import com.tngtech.archunit.core.domain.JavaClasses;
|
||||
import com.tngtech.archunit.core.importer.ClassFileImporter;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link Module}.
|
||||
*
|
||||
* @author Oliver Drotbohm
|
||||
*/
|
||||
@TestInstance(Lifecycle.PER_CLASS)
|
||||
class ModuleUnitTest {
|
||||
|
||||
ClassFileImporter importer = new ClassFileImporter();
|
||||
JavaClasses classes = importer.importPackages("com.acme.withatbean"); //
|
||||
JavaPackage javaPackage = JavaPackage.of(Classes.of(classes), "");
|
||||
|
||||
Module module = new Module(javaPackage, false);
|
||||
|
||||
@Test
|
||||
public void considersExternalSpringBeans() {
|
||||
|
||||
assertThat(module.getSpringBeans()) //
|
||||
.flatExtracting(SpringBean::getFullyQualifiedTypeName) //
|
||||
.contains(DataSource.class.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void discoversPublishedEvents() {
|
||||
|
||||
JavaClass jMoleculesAnnotated = classes.get(JMoleculesAnnotated.class);
|
||||
JavaClass jMoleculesImplementing = classes.get(JMoleculesImplementing.class);
|
||||
|
||||
List<EventType> events = module.getPublishedEvents();
|
||||
|
||||
assertThat(events.stream().map(EventType::getType)) //
|
||||
.containsExactlyInAnyOrder(jMoleculesAnnotated, jMoleculesImplementing);
|
||||
assertThat(events.stream().filter(it -> it.getType().equals(jMoleculesAnnotated))) //
|
||||
.element(0) //
|
||||
.satisfies(it -> {
|
||||
assertThat(it.getSources()).isNotEmpty();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.modulith.model;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.modulith.Modulith;
|
||||
import org.springframework.modulith.Modulithic;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ModulithMetadata}.
|
||||
*
|
||||
* @author Oliver Drotbohm
|
||||
*/
|
||||
class ModulithMetadataUnitTest {
|
||||
|
||||
@Test
|
||||
public void inspectsModulithAnnotation() throws Exception {
|
||||
|
||||
Stream.of(ModulithAnnotated.class, ModuliticAnnotated.class) //
|
||||
.map(ModulithMetadata::of) //
|
||||
.forEach(it -> {
|
||||
|
||||
assertThat(it.getAdditionalPackages()).containsExactly("com.acme.foo");
|
||||
assertThat(it.getSharedModuleNames()).containsExactly("shared.module");
|
||||
assertThat(it.getSystemName()).hasValue("systemName");
|
||||
assertThat(it.useFullyQualifiedModuleNames()).isTrue();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void usesDefaultsIfModulithAnnotationsAreMissing() {
|
||||
|
||||
ModulithMetadata metadata = ModulithMetadata.of(SpringBootApplicationAnnotated.class);
|
||||
|
||||
assertThat(metadata.getAdditionalPackages()).isEmpty();
|
||||
assertThat(metadata.getSharedModuleNames()).isEmpty();
|
||||
assertThat(metadata.getSystemName()).isEmpty();
|
||||
assertThat(metadata.useFullyQualifiedModuleNames()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rejectsTypeNotAnnotatedWithEitherModulithAnnotationOrSpringBootApplication() {
|
||||
|
||||
assertThatExceptionOfType(IllegalArgumentException.class) //
|
||||
.isThrownBy(() -> ModulithMetadata.of(Unannotated.class)) //
|
||||
.withMessageContaining(Modulith.class.getSimpleName()) //
|
||||
.withMessageContaining(Modulithic.class.getSimpleName()) //
|
||||
.withMessageContaining(SpringBootApplication.class.getSimpleName());
|
||||
}
|
||||
|
||||
@Modulith(additionalPackages = "com.acme.foo", //
|
||||
sharedModules = "shared.module", //
|
||||
systemName = "systemName", //
|
||||
useFullyQualifiedModuleNames = true)
|
||||
static class ModulithAnnotated {}
|
||||
|
||||
@Modulithic(additionalPackages = "com.acme.foo", //
|
||||
sharedModules = "shared.module", //
|
||||
systemName = "systemName", //
|
||||
useFullyQualifiedModuleNames = true)
|
||||
static class ModuliticAnnotated {}
|
||||
|
||||
@SpringBootApplication
|
||||
static class SpringBootApplicationAnnotated {}
|
||||
|
||||
static class Unannotated {}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.modulith.model;
|
||||
|
||||
import static com.tngtech.archunit.core.domain.JavaClass.Predicates.*;
|
||||
|
||||
import org.jmolecules.ddd.annotation.AggregateRoot;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.tngtech.archunit.base.DescribedPredicate;
|
||||
import com.tngtech.archunit.core.domain.JavaClass;
|
||||
import com.tngtech.archunit.core.domain.JavaClasses;
|
||||
import com.tngtech.archunit.core.importer.ClassFileImporter;
|
||||
import com.tngtech.archunit.thirdparty.com.google.common.base.Supplier;
|
||||
import com.tngtech.archunit.thirdparty.com.google.common.base.Suppliers;
|
||||
|
||||
/**
|
||||
* Utilities for testing.
|
||||
*
|
||||
* @author Oliver Drotbohm
|
||||
*/
|
||||
class TestUtils {
|
||||
|
||||
private static Supplier<JavaClasses> imported = Suppliers.memoize(() -> new ClassFileImporter() //
|
||||
.importPackagesOf(Modules.class, Repository.class, AggregateRoot.class));
|
||||
|
||||
private static DescribedPredicate<JavaClass> IS_MODULE_TYPE = JavaClass.Predicates
|
||||
.resideInAPackage(Modules.class.getPackage().getName());
|
||||
|
||||
private static Supplier<Classes> classes = Suppliers.memoize(() -> Classes.of(imported.get()).that(IS_MODULE_TYPE));
|
||||
|
||||
/**
|
||||
* Returns all {@link Classes} of this module.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static Classes getClasses() {
|
||||
return classes.get();
|
||||
}
|
||||
|
||||
public static JavaClasses getJavaClasses() {
|
||||
return imported.get().that(IS_MODULE_TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all {@link Classes} in the package of the given type.
|
||||
*
|
||||
* @param packageType must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public static Classes getClasses(Class<?> packageType) {
|
||||
|
||||
Assert.notNull(packageType, "Package type must not be null!");
|
||||
|
||||
return getClasses().that(resideInAPackage(packageType.getPackage().getName()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.modulith.model;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link Violations}.
|
||||
*
|
||||
* @author Oliver Drotbohm
|
||||
*/
|
||||
class ViolationsUnitTests {
|
||||
|
||||
@Test
|
||||
void combinesExceptionMessages() {
|
||||
|
||||
Violations violations = Violations.NONE //
|
||||
.and(new IllegalArgumentException("First")) //
|
||||
.and(new IllegalArgumentException("Second"));
|
||||
|
||||
assertThat(violations.getMessage()) //
|
||||
.isEqualTo("- First\n- Second");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user