Skip to content

Commit

Permalink
test(standalone): add tests and docs
Browse files Browse the repository at this point in the history
  • Loading branch information
timonback committed Feb 18, 2025
1 parent af63403 commit f1455a8
Show file tree
Hide file tree
Showing 10 changed files with 181 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,21 @@

import io.github.springwolf.core.asyncapi.AsyncApiService;
import io.github.springwolf.core.configuration.properties.SpringwolfConfigProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;

import java.util.List;

@Slf4j
/**
* Create a standalone application context using spring mechanisms internally, while skipping Spring Boot auto-configurations.
* <p>
* By default, all Springwolf configuration classes annotated with {@link StandaloneConfiguration} will be registered in the context.
* Use {@link StandaloneConfigurationDiscoverer#scan(String,ConfigurableEnvironment)} to discover configurations
* <p>
* Custom configuration classes or beans can be added,
* for example to override beans or to add a {@link io.github.springwolf.core.asyncapi.AsyncApiCustomizer}
*/
public class DefaultStandaloneFactory implements StandaloneFactory {
private final AnnotationConfigApplicationContext diContext = new AnnotationConfigApplicationContext();

Expand All @@ -22,8 +29,15 @@ public DefaultStandaloneFactory(String applicationBasePackage, ConfigurableEnvir
this(applicationBasePackage, environment, StandaloneConfigurationDiscoverer.scan(environment));
}

/**
* Create a standalone application context with custom configurations
*
* @param applicationBasePackages The application base packages that Springwolf will scan
* @param environment The spring environment to use (e.g. properties, profiles)
* @param standaloneConfigurations All standalone configurations to register in the context
*/
public DefaultStandaloneFactory(
String applicationBasePackage,
String applicationBasePackages,
ConfigurableEnvironment environment,
List<Class<?>> standaloneConfigurations) {
standaloneConfigurations.forEach(diContext::register);
Expand All @@ -32,7 +46,7 @@ public DefaultStandaloneFactory(
diContext.refresh();

// overwrite scanning package
diContext.getBean(SpringwolfConfigProperties.class).getDocket().setBasePackage(applicationBasePackage);
diContext.getBean(SpringwolfConfigProperties.class).getDocket().setBasePackage(applicationBasePackages);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Marker annotation for Springwolf standalone configurations.
* <p>
* Those classes can be discovered by {@link StandaloneConfigurationDiscoverer}.
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface StandaloneConfiguration {}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@

import java.util.List;

/**
* Discovers classes annotated with {@link StandaloneConfiguration}.
*/
public class StandaloneConfigurationDiscoverer {
public static List<Class<?>> scan(ConfigurableEnvironment environment) {
return scan(SpringwolfConfigConstants.SPRINGWOLF_PACKAGE, environment);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

import java.util.List;

/**
* Loads a standalone environment using spring mechanisms including env variables, properties and profiles.
*/
public class StandaloneEnvironmentLoader {
public static ConfigurableEnvironment load() {
return load(List.of());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@
/**
* Factory to create a Springwolf instance and {@link io.github.springwolf.asyncapi.v3.model.AsyncAPI}
* for standalone usage without runtime Spring context.
* <p/>
* Allows usage at compile time, for example in unit test.
* <p/>
* Since no spring context is available, not all features are supported.
* <p>
* Allows Springwolf usage at build time, for example in unit test.
*/
public interface StandaloneFactory {
AsyncApiService getAsyncApiService();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// SPDX-License-Identifier: Apache-2.0
package io.github.springwolf.core.standalone;

import io.github.springwolf.core.integrationtests.application.basic.TestApplication;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.StandardEnvironment;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Fail.fail;

class DefaultStandaloneFactoryTest {

private String applicationPackageName = TestApplication.class.getPackageName();

@Test
void shouldCreateStandaloneFactoryForBasicApplication() {
// when
DefaultStandaloneFactory factory = new DefaultStandaloneFactory(TestApplication.class.getPackageName());

// then
assertThat(factory.getAsyncApiService().getAsyncAPI()).isNotNull();
assertThat(factory.getAsyncApiService().getAsyncAPI().getInfo().getTitle())
.isEqualTo("Springwolf-core");
}

@Test
void shouldCreateStandaloneFactoryForBasicApplicationWithProfile() {
// given
ConfigurableEnvironment environment = StandaloneEnvironmentLoader.load(List.of("standalone"));

// when
DefaultStandaloneFactory factory =
new DefaultStandaloneFactory(TestApplication.class.getPackageName(), environment);

// then
assertThat(factory.getAsyncApiService().getAsyncAPI()).isNotNull();
assertThat(factory.getAsyncApiService().getAsyncAPI().getInfo().getTitle())
.isEqualTo("Springwolf-core-properties");
}

@Test
void shouldThrowWhenConfigurationsAreMissing() {
// when
List<Class<?>> standaloneConfigurations = List.of();

try {
new DefaultStandaloneFactory(applicationPackageName, new StandardEnvironment(), standaloneConfigurations);
fail();
} catch (Exception e) {
assertThat(e).isInstanceOf(NoSuchBeanDefinitionException.class);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// SPDX-License-Identifier: Apache-2.0
package io.github.springwolf.core.standalone;

import org.junit.jupiter.api.Test;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.StandardEnvironment;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;

class StandaloneConfigurationDiscovererTest {
private final ConfigurableEnvironment environment = new StandardEnvironment();

@Test
void shouldFindAllCoreStandaloneConfigurations() {
// when
List<String> classes = StandaloneConfigurationDiscoverer.scan(environment).stream()
.map(Class::getName)
.toList();

// then
assertThat(classes)
.containsExactlyInAnyOrder( //
"io.github.springwolf.core.configuration.SpringwolfCoreConfiguration",
"io.github.springwolf.core.configuration.SpringwolfPropertiesConfiguration",
"io.github.springwolf.core.configuration.SpringwolfScannerConfiguration",
"io.github.springwolf.addons.common_model_converters.configuration.CommonModelConvertersAutoConfiguration");
}

@Test
void shouldFindAllConfigurationsInPackage() {
// when
List<String> classes =
StandaloneConfigurationDiscoverer.scan("io.github.springwolf.non.existing.package", environment)
.stream()
.map(Class::getName)
.toList();

// then
assertThat(classes).containsExactlyInAnyOrder();
}

@Test
void shouldFindAllCoreConfigurationsInPackage() {
// when
List<String> classes = StandaloneConfigurationDiscoverer.scan("io.github.springwolf.core", environment).stream()
.map(Class::getName)
.toList();

// then
assertThat(classes)
.containsExactlyInAnyOrder(
"io.github.springwolf.core.configuration.SpringwolfCoreConfiguration",
"io.github.springwolf.core.configuration.SpringwolfPropertiesConfiguration",
"io.github.springwolf.core.configuration.SpringwolfScannerConfiguration");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// SPDX-License-Identifier: Apache-2.0
package io.github.springwolf.core.standalone;

import org.junit.jupiter.api.Test;
import org.springframework.core.env.ConfigurableEnvironment;

import java.util.List;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;

class StandaloneEnvironmentLoaderTest {

@Test
void shouldLoadDefaultEnvironmentTest() {
// when
ConfigurableEnvironment environment = StandaloneEnvironmentLoader.load();

// then
assertThat(environment.getActiveProfiles()).containsExactly();
assertThat(environment.getProperty("spring.application.name")).isEqualTo("Springwolf-core");
}

@Test
void shouldLoadStandaloneProfileIncludingPropertyFile() {
// when
ConfigurableEnvironment environment = StandaloneEnvironmentLoader.load(List.of("standalone"));

// then
assertThat(environment.getActiveProfiles()).containsExactly("standalone");
assertThat(environment.getProperty("spring.application.name")).isEqualTo("Springwolf-core-properties");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
spring.application.name=Springwolf-core-properties
2 changes: 2 additions & 0 deletions springwolf-core/src/test/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ springwolf.docket.base-package=io.github.springwolf.core
springwolf.docket.info.title=${spring.application.name}
springwolf.docket.info.version=1.0.0
springwolf.docket.info.description=Springwolf example project to demonstrate springwolfs abilities
springwolf.docket.servers.test-protocol.protocol=property-protocol
springwolf.docket.servers.test-protocol.host=some-property-server:1234

0 comments on commit f1455a8

Please sign in to comment.