Tidy up tests in spring-boot-autoconfigure-all
This commit is contained in:
committed by
Phillip Webb
parent
6e04fc0910
commit
5b4791fdc6
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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.boot.autoconfigure.admin;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
|
||||
import javax.management.InstanceNotFoundException;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.MalformedObjectNameException;
|
||||
import javax.management.ObjectInstance;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.boot.WebApplicationType;
|
||||
import org.springframework.boot.admin.SpringApplicationAdminMXBeanRegistrar;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.jmx.export.MBeanExporter;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.Assertions.fail;
|
||||
|
||||
/**
|
||||
* Tests for {@link SpringApplicationAdminJmxAutoConfiguration}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Andy Wilkinson
|
||||
* @author Nguyen Bao Sach
|
||||
*/
|
||||
class SpringApplicationAdminJmxAutoConfigurationTests {
|
||||
|
||||
private static final String ENABLE_ADMIN_PROP = "spring.application.admin.enabled=true";
|
||||
|
||||
private static final String DEFAULT_JMX_NAME = "org.springframework.boot:type=Admin,name=SpringApplication";
|
||||
|
||||
private final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(SpringApplicationAdminJmxAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void notRegisteredWhenThereAreNoMBeanExporter() {
|
||||
this.contextRunner.withPropertyValues(ENABLE_ADMIN_PROP).run((context) -> {
|
||||
ObjectName objectName = createDefaultObjectName();
|
||||
ObjectInstance objectInstance = this.server.getObjectInstance(objectName);
|
||||
assertThat(objectInstance).as("Lifecycle bean should have been registered").isNotNull();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void notRegisteredByDefaultWhenThereAreMultipleMBeanExporters() {
|
||||
this.contextRunner.withUserConfiguration(MultipleMBeanExportersConfiguration.class)
|
||||
.run((context) -> assertThatExceptionOfType(InstanceNotFoundException.class)
|
||||
.isThrownBy(() -> this.server.getObjectInstance(createDefaultObjectName())));
|
||||
}
|
||||
|
||||
@Test
|
||||
void registeredWithPropertyWhenThereAreMultipleMBeanExporters() {
|
||||
this.contextRunner.withUserConfiguration(MultipleMBeanExportersConfiguration.class)
|
||||
.withPropertyValues(ENABLE_ADMIN_PROP)
|
||||
.run((context) -> {
|
||||
ObjectName objectName = createDefaultObjectName();
|
||||
ObjectInstance objectInstance = this.server.getObjectInstance(objectName);
|
||||
assertThat(objectInstance).as("Lifecycle bean should have been registered").isNotNull();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void registerWithCustomJmxNameWhenThereAreMultipleMBeanExporters() {
|
||||
String customJmxName = "org.acme:name=FooBar";
|
||||
this.contextRunner.withUserConfiguration(MultipleMBeanExportersConfiguration.class)
|
||||
.withSystemProperties("spring.application.admin.jmx-name=" + customJmxName)
|
||||
.withPropertyValues(ENABLE_ADMIN_PROP)
|
||||
.run((context) -> {
|
||||
try {
|
||||
this.server.getObjectInstance(createObjectName(customJmxName));
|
||||
}
|
||||
catch (InstanceNotFoundException ex) {
|
||||
fail("Admin MBean should have been exposed with custom name");
|
||||
}
|
||||
assertThatExceptionOfType(InstanceNotFoundException.class)
|
||||
.isThrownBy(() -> this.server.getObjectInstance(createDefaultObjectName()));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void onlyRegisteredOnceWhenThereIsAChildContext() {
|
||||
SpringApplicationBuilder parentBuilder = new SpringApplicationBuilder().web(WebApplicationType.NONE)
|
||||
.sources(MultipleMBeanExportersConfiguration.class, SpringApplicationAdminJmxAutoConfiguration.class);
|
||||
SpringApplicationBuilder childBuilder = parentBuilder
|
||||
.child(MultipleMBeanExportersConfiguration.class, SpringApplicationAdminJmxAutoConfiguration.class)
|
||||
.web(WebApplicationType.NONE);
|
||||
try (ConfigurableApplicationContext parent = parentBuilder.run("--" + ENABLE_ADMIN_PROP);
|
||||
ConfigurableApplicationContext child = childBuilder.run("--" + ENABLE_ADMIN_PROP)) {
|
||||
BeanFactoryUtils.beanOfType(parent.getBeanFactory(), SpringApplicationAdminMXBeanRegistrar.class);
|
||||
assertThatExceptionOfType(NoSuchBeanDefinitionException.class).isThrownBy(() -> BeanFactoryUtils
|
||||
.beanOfType(child.getBeanFactory(), SpringApplicationAdminMXBeanRegistrar.class));
|
||||
}
|
||||
}
|
||||
|
||||
private ObjectName createDefaultObjectName() {
|
||||
return createObjectName(DEFAULT_JMX_NAME);
|
||||
}
|
||||
|
||||
private ObjectName createObjectName(String jmxName) {
|
||||
try {
|
||||
return new ObjectName(jmxName);
|
||||
}
|
||||
catch (MalformedObjectNameException ex) {
|
||||
throw new IllegalStateException("Invalid jmx name " + jmxName, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class MultipleMBeanExportersConfiguration {
|
||||
|
||||
@Bean
|
||||
MBeanExporter firstMBeanExporter() {
|
||||
return new MBeanExporter();
|
||||
}
|
||||
|
||||
@Bean
|
||||
MBeanExporter secondMBeanExporter() {
|
||||
return new MBeanExporter();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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.boot.autoconfigure.condition;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import jakarta.servlet.Filter;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.ServletRequest;
|
||||
import jakarta.servlet.ServletResponse;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link ConditionalOnMissingFilterBean @ConditionalOnMissingFilterBean}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class ConditionalOnMissingFilterBeanTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner();
|
||||
|
||||
@Test
|
||||
void outcomeWhenValueIsOfMissingBeanReturnsMatch() {
|
||||
this.contextRunner.withUserConfiguration(WithoutTestFilterConfig.class, OnMissingWithValueConfig.class)
|
||||
.run((context) -> assertThat(context).satisfies(filterBeanRequirement("myOtherFilter", "testFilter")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void outcomeWhenValueIsOfExistingBeanReturnsNoMatch() {
|
||||
this.contextRunner.withUserConfiguration(WithTestFilterConfig.class, OnMissingWithValueConfig.class)
|
||||
.run((context) -> assertThat(context).satisfies(filterBeanRequirement("myTestFilter")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void outcomeWhenValueIsOfMissingBeanRegistrationReturnsMatch() {
|
||||
this.contextRunner
|
||||
.withUserConfiguration(WithoutTestFilterRegistrationConfig.class, OnMissingWithValueConfig.class)
|
||||
.run((context) -> assertThat(context).satisfies(filterBeanRequirement("myOtherFilter", "testFilter")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void outcomeWhenValueIsOfExistingBeanRegistrationReturnsNoMatch() {
|
||||
this.contextRunner.withUserConfiguration(WithTestFilterRegistrationConfig.class, OnMissingWithValueConfig.class)
|
||||
.run((context) -> assertThat(context).satisfies(filterBeanRequirement("myTestFilter")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void outcomeWhenReturnTypeIsOfExistingBeanReturnsNoMatch() {
|
||||
this.contextRunner.withUserConfiguration(WithTestFilterConfig.class, OnMissingWithReturnTypeConfig.class)
|
||||
.run((context) -> assertThat(context).satisfies(filterBeanRequirement("myTestFilter")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void outcomeWhenReturnTypeIsOfExistingBeanRegistrationReturnsNoMatch() {
|
||||
this.contextRunner
|
||||
.withUserConfiguration(WithTestFilterRegistrationConfig.class, OnMissingWithReturnTypeConfig.class)
|
||||
.run((context) -> assertThat(context).satisfies(filterBeanRequirement("myTestFilter")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void outcomeWhenReturnRegistrationTypeIsOfExistingBeanReturnsNoMatch() {
|
||||
this.contextRunner
|
||||
.withUserConfiguration(WithTestFilterConfig.class, OnMissingWithReturnRegistrationTypeConfig.class)
|
||||
.run((context) -> assertThat(context).satisfies(filterBeanRequirement("myTestFilter")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void outcomeWhenReturnRegistrationTypeIsOfExistingBeanRegistrationReturnsNoMatch() {
|
||||
this.contextRunner
|
||||
.withUserConfiguration(WithTestFilterRegistrationConfig.class,
|
||||
OnMissingWithReturnRegistrationTypeConfig.class)
|
||||
.run((context) -> assertThat(context).satisfies(filterBeanRequirement("myTestFilter")));
|
||||
}
|
||||
|
||||
private Consumer<ConfigurableApplicationContext> filterBeanRequirement(String... names) {
|
||||
return (context) -> {
|
||||
String[] filters = context.getBeanNamesForType(Filter.class);
|
||||
String[] registrations = context.getBeanNamesForType(FilterRegistrationBean.class);
|
||||
assertThat(StringUtils.concatenateStringArrays(filters, registrations)).containsOnly(names);
|
||||
};
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class WithTestFilterConfig {
|
||||
|
||||
@Bean
|
||||
TestFilter myTestFilter() {
|
||||
return new TestFilter();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class WithoutTestFilterConfig {
|
||||
|
||||
@Bean
|
||||
OtherFilter myOtherFilter() {
|
||||
return new OtherFilter();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class WithoutTestFilterRegistrationConfig {
|
||||
|
||||
@Bean
|
||||
FilterRegistrationBean<OtherFilter> myOtherFilter() {
|
||||
return new FilterRegistrationBean<>(new OtherFilter());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class WithTestFilterRegistrationConfig {
|
||||
|
||||
@Bean
|
||||
FilterRegistrationBean<TestFilter> myTestFilter() {
|
||||
return new FilterRegistrationBean<>(new TestFilter());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class OnMissingWithValueConfig {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingFilterBean(TestFilter.class)
|
||||
TestFilter testFilter() {
|
||||
return new TestFilter();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class OnMissingWithReturnTypeConfig {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingFilterBean
|
||||
TestFilter testFilter() {
|
||||
return new TestFilter();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class OnMissingWithReturnRegistrationTypeConfig {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingFilterBean
|
||||
FilterRegistrationBean<TestFilter> testFilter() {
|
||||
return new FilterRegistrationBean<>(new TestFilter());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class TestFilter implements Filter {
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class OtherFilter implements Filter {
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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.boot.autoconfigure.container;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.core.AttributeAccessor;
|
||||
import org.springframework.core.AttributeAccessorSupport;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link ContainerImageMetadata}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class ContainerImageMetadataTests {
|
||||
|
||||
private ContainerImageMetadata metadata = new ContainerImageMetadata("test");
|
||||
|
||||
private AttributeAccessor attributes = new AttributeAccessorSupport() {
|
||||
|
||||
};
|
||||
|
||||
@Test
|
||||
void addToWhenAttributesIsNullDoesNothing() {
|
||||
this.metadata.addTo(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
void addToAddsMetadata() {
|
||||
this.metadata.addTo(this.attributes);
|
||||
assertThat(this.attributes.getAttribute(ContainerImageMetadata.NAME)).isSameAs(this.metadata);
|
||||
}
|
||||
|
||||
@Test
|
||||
void isPresentWhenPresentReturnsTrue() {
|
||||
this.metadata.addTo(this.attributes);
|
||||
assertThat(ContainerImageMetadata.isPresent(this.attributes)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void isPresentWhenNotPresentReturnsFalse() {
|
||||
assertThat(ContainerImageMetadata.isPresent(this.attributes)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void isPresentWhenNullAttributesReturnsFalse() {
|
||||
assertThat(ContainerImageMetadata.isPresent(null)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getFromWhenPresentReturnsMetadata() {
|
||||
this.metadata.addTo(this.attributes);
|
||||
assertThat(ContainerImageMetadata.getFrom(this.attributes)).isSameAs(this.metadata);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getFromWhenNotPresentReturnsNull() {
|
||||
assertThat(ContainerImageMetadata.getFrom(this.attributes)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getFromWhenNullAttributesReturnsNull() {
|
||||
assertThat(ContainerImageMetadata.getFrom(null)).isNull();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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.boot.autoconfigure.template;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.BDDMockito.then;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
|
||||
/**
|
||||
* Tests for {@link TemplateAvailabilityProviders}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class TemplateAvailabilityProvidersTests {
|
||||
|
||||
private TemplateAvailabilityProviders providers;
|
||||
|
||||
@Mock
|
||||
private TemplateAvailabilityProvider provider;
|
||||
|
||||
private final String view = "view";
|
||||
|
||||
private final ClassLoader classLoader = getClass().getClassLoader();
|
||||
|
||||
private final MockEnvironment environment = new MockEnvironment();
|
||||
|
||||
@Mock
|
||||
private ResourceLoader resourceLoader;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
this.providers = new TemplateAvailabilityProviders(Collections.singleton(this.provider));
|
||||
}
|
||||
|
||||
@Test
|
||||
void createWhenApplicationContextIsNullShouldThrowException() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new TemplateAvailabilityProviders((ApplicationContext) null))
|
||||
.withMessageContaining("'classLoader' must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("rawtypes")
|
||||
@WithTestTemplateAvailabilityProvider
|
||||
void createWhenUsingApplicationContextShouldLoadProviders() {
|
||||
ApplicationContext applicationContext = mock(ApplicationContext.class);
|
||||
given(applicationContext.getClassLoader()).willReturn(Thread.currentThread().getContextClassLoader());
|
||||
TemplateAvailabilityProviders providers = new TemplateAvailabilityProviders(applicationContext);
|
||||
assertThat(providers.getProviders()).extracting((provider) -> (Class) provider.getClass())
|
||||
.containsExactly(TestTemplateAvailabilityProvider.class);
|
||||
then(applicationContext).should().getClassLoader();
|
||||
}
|
||||
|
||||
@Test
|
||||
void createWhenClassLoaderIsNullShouldThrowException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new TemplateAvailabilityProviders((ClassLoader) null))
|
||||
.withMessageContaining("'classLoader' must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithTestTemplateAvailabilityProvider
|
||||
void createWhenUsingClassLoaderShouldLoadProviders() {
|
||||
TemplateAvailabilityProviders providers = new TemplateAvailabilityProviders(
|
||||
Thread.currentThread().getContextClassLoader());
|
||||
assertThat(providers.getProviders()).isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void createWhenProvidersIsNullShouldThrowException() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new TemplateAvailabilityProviders((Collection<TemplateAvailabilityProvider>) null))
|
||||
.withMessageContaining("'providers' must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
void createWhenUsingProvidersShouldUseProviders() {
|
||||
TemplateAvailabilityProviders providers = new TemplateAvailabilityProviders(
|
||||
Collections.singleton(this.provider));
|
||||
assertThat(providers.getProviders()).containsOnly(this.provider);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getProviderWhenApplicationContextIsNullShouldThrowException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> this.providers.getProvider(this.view, null))
|
||||
.withMessageContaining("'applicationContext' must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getProviderWhenViewIsNullShouldThrowException() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> this.providers.getProvider(null, this.environment, this.classLoader, this.resourceLoader))
|
||||
.withMessageContaining("'view' must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getProviderWhenEnvironmentIsNullShouldThrowException() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> this.providers.getProvider(this.view, null, this.classLoader, this.resourceLoader))
|
||||
.withMessageContaining("'environment' must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getProviderWhenClassLoaderIsNullShouldThrowException() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> this.providers.getProvider(this.view, this.environment, null, this.resourceLoader))
|
||||
.withMessageContaining("'classLoader' must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getProviderWhenResourceLoaderIsNullShouldThrowException() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> this.providers.getProvider(this.view, this.environment, this.classLoader, null))
|
||||
.withMessageContaining("'resourceLoader' must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getProviderWhenNoneMatchShouldReturnNull() {
|
||||
TemplateAvailabilityProvider found = this.providers.getProvider(this.view, this.environment, this.classLoader,
|
||||
this.resourceLoader);
|
||||
assertThat(found).isNull();
|
||||
then(this.provider).should()
|
||||
.isTemplateAvailable(this.view, this.environment, this.classLoader, this.resourceLoader);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getProviderWhenMatchShouldReturnProvider() {
|
||||
given(this.provider.isTemplateAvailable(this.view, this.environment, this.classLoader, this.resourceLoader))
|
||||
.willReturn(true);
|
||||
TemplateAvailabilityProvider found = this.providers.getProvider(this.view, this.environment, this.classLoader,
|
||||
this.resourceLoader);
|
||||
assertThat(found).isSameAs(this.provider);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void getProviderShouldCacheMatchResult() {
|
||||
given(this.provider.isTemplateAvailable(this.view, this.environment, this.classLoader, this.resourceLoader))
|
||||
.willReturn(true);
|
||||
this.providers.getProvider(this.view, this.environment, this.classLoader, this.resourceLoader);
|
||||
this.providers.getProvider(this.view, this.environment, this.classLoader, this.resourceLoader);
|
||||
then(this.provider).should()
|
||||
.isTemplateAvailable(this.view, this.environment, this.classLoader, this.resourceLoader);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getProviderShouldCacheNoMatchResult() {
|
||||
this.providers.getProvider(this.view, this.environment, this.classLoader, this.resourceLoader);
|
||||
this.providers.getProvider(this.view, this.environment, this.classLoader, this.resourceLoader);
|
||||
then(this.provider).should()
|
||||
.isTemplateAvailable(this.view, this.environment, this.classLoader, this.resourceLoader);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getProviderWhenCacheDisabledShouldNotUseCache() {
|
||||
given(this.provider.isTemplateAvailable(this.view, this.environment, this.classLoader, this.resourceLoader))
|
||||
.willReturn(true);
|
||||
this.environment.setProperty("spring.template.provider.cache", "false");
|
||||
this.providers.getProvider(this.view, this.environment, this.classLoader, this.resourceLoader);
|
||||
this.providers.getProvider(this.view, this.environment, this.classLoader, this.resourceLoader);
|
||||
then(this.provider).should(times(2))
|
||||
.isTemplateAvailable(this.view, this.environment, this.classLoader, this.resourceLoader);
|
||||
}
|
||||
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@WithResource(name = "META-INF/spring.factories",
|
||||
content = "org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider="
|
||||
+ "org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvidersTests$TestTemplateAvailabilityProvider")
|
||||
@interface WithTestTemplateAvailabilityProvider {
|
||||
|
||||
}
|
||||
|
||||
static class TestTemplateAvailabilityProvider implements TemplateAvailabilityProvider {
|
||||
|
||||
@Override
|
||||
public boolean isTemplateAvailable(String view, Environment environment, ClassLoader classLoader,
|
||||
ResourceLoader resourceLoader) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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.boot.autoconfigure.template;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.aot.hint.RuntimeHintsRegistrar;
|
||||
import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
|
||||
import org.springframework.beans.factory.aot.AotServices;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link TemplateRuntimeHints}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class TemplateRuntimeHintsTests {
|
||||
|
||||
private static final Predicate<RuntimeHints> TEST_PREDICATE = RuntimeHintsPredicates.resource()
|
||||
.forResource("templates/something/hello.html");
|
||||
|
||||
@Test
|
||||
void templateRuntimeHintsIsRegistered() {
|
||||
Iterable<RuntimeHintsRegistrar> registrar = AotServices.factories().load(RuntimeHintsRegistrar.class);
|
||||
assertThat(registrar).anyMatch(TemplateRuntimeHints.class::isInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "templates/test.html")
|
||||
void contributeWhenTemplateLocationExists() {
|
||||
RuntimeHints runtimeHints = contribute(Thread.currentThread().getContextClassLoader());
|
||||
assertThat(TEST_PREDICATE.test(runtimeHints)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void contributeWhenTemplateLocationDoesNotExist() {
|
||||
FilteredClassLoader classLoader = new FilteredClassLoader(new ClassPathResource("templates"));
|
||||
RuntimeHints runtimeHints = contribute(classLoader);
|
||||
assertThat(TEST_PREDICATE.test(runtimeHints)).isFalse();
|
||||
}
|
||||
|
||||
private RuntimeHints contribute(ClassLoader classLoader) {
|
||||
RuntimeHints runtimeHints = new RuntimeHints();
|
||||
new TemplateRuntimeHints().registerHints(runtimeHints, classLoader);
|
||||
return runtimeHints;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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.boot.autoconfigure.web.format;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.OffsetTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.FormatStyle;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link WebConversionService}.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
* @author Madhura Bhave
|
||||
* @author Gaurav Pareek
|
||||
*/
|
||||
class WebConversionServiceTests {
|
||||
|
||||
@Test
|
||||
void defaultDateFormat() {
|
||||
WebConversionService conversionService = new WebConversionService(new DateTimeFormatters());
|
||||
LocalDate date = LocalDate.of(2020, 4, 26);
|
||||
assertThat(conversionService.convert(date, String.class))
|
||||
.isEqualTo(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT).format(date));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isoDateFormat() {
|
||||
WebConversionService conversionService = new WebConversionService(new DateTimeFormatters().dateFormat("iso"));
|
||||
LocalDate date = LocalDate.of(2020, 4, 26);
|
||||
assertThat(conversionService.convert(date, String.class))
|
||||
.isEqualTo(DateTimeFormatter.ISO_LOCAL_DATE.format(date));
|
||||
}
|
||||
|
||||
@Test
|
||||
void customDateFormatWithJavaUtilDate() {
|
||||
customDateFormat(Date.from(ZonedDateTime.of(2018, 1, 1, 20, 30, 0, 0, ZoneId.systemDefault()).toInstant()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void customDateFormatWithJavaTime() {
|
||||
customDateFormat(java.time.LocalDate.of(2018, 1, 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void defaultTimeFormat() {
|
||||
WebConversionService conversionService = new WebConversionService(new DateTimeFormatters());
|
||||
LocalTime time = LocalTime.of(12, 45, 23);
|
||||
assertThat(conversionService.convert(time, String.class))
|
||||
.isEqualTo(DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT).format(time));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isoTimeFormat() {
|
||||
WebConversionService conversionService = new WebConversionService(new DateTimeFormatters().timeFormat("iso"));
|
||||
LocalTime time = LocalTime.of(12, 45, 23);
|
||||
assertThat(conversionService.convert(time, String.class))
|
||||
.isEqualTo(DateTimeFormatter.ISO_LOCAL_TIME.format(time));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isoOffsetTimeFormat() {
|
||||
isoOffsetTimeFormat(new DateTimeFormatters().timeFormat("isooffset"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void hyphenatedIsoOffsetTimeFormat() {
|
||||
isoOffsetTimeFormat(new DateTimeFormatters().timeFormat("iso-offset"));
|
||||
}
|
||||
|
||||
private void isoOffsetTimeFormat(DateTimeFormatters formatters) {
|
||||
WebConversionService conversionService = new WebConversionService(formatters);
|
||||
OffsetTime offsetTime = OffsetTime.of(LocalTime.of(12, 45, 23), ZoneOffset.ofHoursMinutes(1, 30));
|
||||
assertThat(conversionService.convert(offsetTime, String.class))
|
||||
.isEqualTo(DateTimeFormatter.ISO_OFFSET_TIME.format(offsetTime));
|
||||
}
|
||||
|
||||
@Test
|
||||
void customTimeFormat() {
|
||||
WebConversionService conversionService = new WebConversionService(
|
||||
new DateTimeFormatters().timeFormat("HH*mm*ss"));
|
||||
LocalTime time = LocalTime.of(12, 45, 23);
|
||||
assertThat(conversionService.convert(time, String.class)).isEqualTo("12*45*23");
|
||||
}
|
||||
|
||||
@Test
|
||||
void defaultDateTimeFormat() {
|
||||
WebConversionService conversionService = new WebConversionService(new DateTimeFormatters());
|
||||
LocalDateTime dateTime = LocalDateTime.of(2020, 4, 26, 12, 45, 23);
|
||||
assertThat(conversionService.convert(dateTime, String.class))
|
||||
.isEqualTo(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).format(dateTime));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isoDateTimeFormat() {
|
||||
WebConversionService conversionService = new WebConversionService(
|
||||
new DateTimeFormatters().dateTimeFormat("iso"));
|
||||
LocalDateTime dateTime = LocalDateTime.of(2020, 4, 26, 12, 45, 23);
|
||||
assertThat(conversionService.convert(dateTime, String.class))
|
||||
.isEqualTo(DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(dateTime));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isoOffsetDateTimeFormat() {
|
||||
isoOffsetDateTimeFormat(new DateTimeFormatters().dateTimeFormat("isooffset"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void hyphenatedIsoOffsetDateTimeFormat() {
|
||||
isoOffsetDateTimeFormat(new DateTimeFormatters().dateTimeFormat("iso-offset"));
|
||||
}
|
||||
|
||||
private void isoOffsetDateTimeFormat(DateTimeFormatters formatters) {
|
||||
WebConversionService conversionService = new WebConversionService(formatters);
|
||||
OffsetDateTime offsetDateTime = OffsetDateTime.of(LocalDate.of(2020, 4, 26), LocalTime.of(12, 45, 23),
|
||||
ZoneOffset.ofHoursMinutes(1, 30));
|
||||
assertThat(conversionService.convert(offsetDateTime, String.class))
|
||||
.isEqualTo(DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(offsetDateTime));
|
||||
}
|
||||
|
||||
@Test
|
||||
void customDateTimeFormat() {
|
||||
WebConversionService conversionService = new WebConversionService(
|
||||
new DateTimeFormatters().dateTimeFormat("dd*MM*yyyy HH*mm*ss"));
|
||||
LocalDateTime dateTime = LocalDateTime.of(2020, 4, 26, 12, 45, 23);
|
||||
assertThat(conversionService.convert(dateTime, String.class)).isEqualTo("26*04*2020 12*45*23");
|
||||
}
|
||||
|
||||
@Test
|
||||
void convertFromStringToLocalDate() {
|
||||
WebConversionService conversionService = new WebConversionService(
|
||||
new DateTimeFormatters().dateFormat("yyyy-MM-dd"));
|
||||
LocalDate date = conversionService.convert("2018-01-01", LocalDate.class);
|
||||
assertThat(date).isEqualTo(java.time.LocalDate.of(2018, 1, 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void convertFromStringToLocalDateWithIsoFormatting() {
|
||||
WebConversionService conversionService = new WebConversionService(new DateTimeFormatters().dateFormat("iso"));
|
||||
LocalDate date = conversionService.convert("2018-01-01", LocalDate.class);
|
||||
assertThat(date).isEqualTo(java.time.LocalDate.of(2018, 1, 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void convertFromStringToDateWithIsoFormatting() {
|
||||
WebConversionService conversionService = new WebConversionService(new DateTimeFormatters().dateFormat("iso"));
|
||||
Date date = conversionService.convert("2018-01-01", Date.class);
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(date);
|
||||
assertThat(calendar.get(Calendar.YEAR)).isEqualTo(2018);
|
||||
assertThat(calendar.get(Calendar.MONTH)).isZero();
|
||||
assertThat(calendar.get(Calendar.DAY_OF_MONTH)).isOne();
|
||||
}
|
||||
|
||||
private void customDateFormat(Object input) {
|
||||
WebConversionService conversionService = new WebConversionService(
|
||||
new DateTimeFormatters().dateFormat("dd*MM*yyyy"));
|
||||
assertThat(conversionService.convert(input, String.class)).isEqualTo("01*01*2018");
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user