Remove spring-boot-json-test module

Remove spring-boot-json-test module and spread code between
`spring-boot-test`, `spring-boot-test-autoconfigure` and JSON
technology modules.

See gh-46356
See gh-47322
This commit is contained in:
Phillip Webb 2025-09-26 18:57:06 -07:00
parent 4b2d358384
commit 8008076e04
127 changed files with 1674 additions and 631 deletions

View File

@ -80,6 +80,8 @@ final class ArchitectureRules {
private static final String AUTOCONFIGURATION_ANNOTATION = "org.springframework.boot.autoconfigure.AutoConfiguration"; private static final String AUTOCONFIGURATION_ANNOTATION = "org.springframework.boot.autoconfigure.AutoConfiguration";
private static final String TEST_AUTOCONFIGURATION_ANNOTATION = "org.springframework.boot.test.autoconfigure.TestAutoConfiguration";
private ArchitectureRules() { private ArchitectureRules() {
} }
@ -112,6 +114,7 @@ final class ArchitectureRules {
rules.add(allConfigurationPropertiesBindingBeanMethodsShouldBeStatic()); rules.add(allConfigurationPropertiesBindingBeanMethodsShouldBeStatic());
rules.add(autoConfigurationClassesShouldBePublicAndFinal()); rules.add(autoConfigurationClassesShouldBePublicAndFinal());
rules.add(autoConfigurationClassesShouldHaveNoPublicMembers()); rules.add(autoConfigurationClassesShouldHaveNoPublicMembers());
rules.add(testAutoConfigurationClassesShouldBePackagePrivateAndFinal());
return List.copyOf(rules); return List.copyOf(rules);
} }
@ -358,8 +361,7 @@ final class ArchitectureRules {
private static ArchRule autoConfigurationClassesShouldBePublicAndFinal() { private static ArchRule autoConfigurationClassesShouldBePublicAndFinal() {
return ArchRuleDefinition.classes() return ArchRuleDefinition.classes()
.that() .that(areRegularAutoConfiguration())
.areAnnotatedWith(AUTOCONFIGURATION_ANNOTATION)
.should() .should()
.bePublic() .bePublic()
.andShould() .andShould()
@ -370,8 +372,7 @@ final class ArchitectureRules {
private static ArchRule autoConfigurationClassesShouldHaveNoPublicMembers() { private static ArchRule autoConfigurationClassesShouldHaveNoPublicMembers() {
return ArchRuleDefinition.members() return ArchRuleDefinition.members()
.that() .that()
.areDeclaredInClassesThat() .areDeclaredInClassesThat(areRegularAutoConfiguration())
.areAnnotatedWith(AUTOCONFIGURATION_ANNOTATION)
.and(areNotDefaultConstructors()) .and(areNotDefaultConstructors())
.and(areNotConstants()) .and(areNotConstants())
.and(dontOverridePublicMethods()) .and(dontOverridePublicMethods())
@ -380,6 +381,24 @@ final class ArchitectureRules {
.allowEmptyShould(true); .allowEmptyShould(true);
} }
private static ArchRule testAutoConfigurationClassesShouldBePackagePrivateAndFinal() {
return ArchRuleDefinition.classes()
.that()
.areAnnotatedWith(TEST_AUTOCONFIGURATION_ANNOTATION)
.should()
.bePackagePrivate()
.andShould()
.haveModifier(JavaModifier.FINAL)
.allowEmptyShould(true);
}
private static DescribedPredicate<JavaClass> areRegularAutoConfiguration() {
return DescribedPredicate.describe("Regular @AutoConfiguration",
(javaClass) -> javaClass.isMetaAnnotatedWith(AUTOCONFIGURATION_ANNOTATION)
&& !javaClass.isMetaAnnotatedWith(TEST_AUTOCONFIGURATION_ANNOTATION)
&& !javaClass.isAnnotation());
}
private static DescribedPredicate<? super JavaMember> dontOverridePublicMethods() { private static DescribedPredicate<? super JavaMember> dontOverridePublicMethods() {
OverridesPublicMethod<JavaMember> predicate = new OverridesPublicMethod<>(); OverridesPublicMethod<JavaMember> predicate = new OverridesPublicMethod<>();
return DescribedPredicate.describe("don't override public methods", (member) -> !predicate.test(member)); return DescribedPredicate.describe("don't override public methods", (member) -> !predicate.test(member));

View File

@ -28,6 +28,7 @@ dependencies {
compileOnly("org.mockito:mockito-core") compileOnly("org.mockito:mockito-core")
optional(project(":core:spring-boot-autoconfigure")) optional(project(":core:spring-boot-autoconfigure"))
optional("jakarta.json.bind:jakarta.json.bind-api")
optional("org.junit.jupiter:junit-jupiter-api") optional("org.junit.jupiter:junit-jupiter-api")
testImplementation(project(":test-support:spring-boot-test-support")) testImplementation(project(":test-support:spring-boot-test-support"))

View File

@ -0,0 +1,80 @@
/*
* Copyright 2012-present 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.test.autoconfigure;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.AliasFor;
/**
* Indicates that a class provides configuration that can be automatically applied by
* Spring Boot tests. Test Auto-configuration classes are regular
* {@link AutoConfiguration @AutoConfiguration} classes but may be package-private.
*
* @author Phillip Webb
* @see AutoConfiguration
* @since 4.0.0
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration(proxyBeanMethods = false)
@AutoConfiguration
public @interface TestAutoConfiguration {
/**
* Alias for {@link AutoConfiguration#value()}.
* @return the aliased value
*/
@AliasFor(annotation = AutoConfiguration.class)
String value() default "";
/**
* Alias for {@link AutoConfiguration#before()}.
* @return the aliased value
*/
@AliasFor(annotation = AutoConfiguration.class)
Class<?>[] before() default {};
/**
* Alias for {@link AutoConfiguration#beforeName()}.
* @return the aliased value
*/
@AliasFor(annotation = AutoConfiguration.class)
String[] beforeName() default {};
/**
* Alias for {@link AutoConfiguration#after()}.
* @return the aliased value
*/
@AliasFor(annotation = AutoConfiguration.class)
Class<?>[] after() default {};
/**
* Alias for {@link AutoConfiguration#afterName()}.
* @return the aliased value
*/
@AliasFor(annotation = AutoConfiguration.class)
String[] afterName() default {};
}

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test.autoconfigure; package org.springframework.boot.test.autoconfigure.json;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
@ -31,7 +31,7 @@ import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
* annotation directly. * annotation directly.
* *
* @author Phillip Webb * @author Phillip Webb
* @since 4.0.0 * @since 1.4.0
* @see JsonTest * @see JsonTest
*/ */
@Target(ElementType.TYPE) @Target(ElementType.TYPE)

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test.autoconfigure; package org.springframework.boot.test.autoconfigure.json;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
@ -24,18 +24,18 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.json.test.BasicJsonTester;
import org.springframework.boot.json.test.GsonTester;
import org.springframework.boot.json.test.JacksonTester;
import org.springframework.boot.json.test.JsonbTester;
import org.springframework.boot.test.context.PropertyMapping; import org.springframework.boot.test.context.PropertyMapping;
import org.springframework.boot.test.json.BasicJsonTester;
import org.springframework.boot.test.json.GsonTester;
import org.springframework.boot.test.json.JacksonTester;
import org.springframework.boot.test.json.JsonbTester;
/** /**
* Annotation that can be applied to a test class to enable and configure * Annotation that can be applied to a test class to enable and configure
* auto-configuration of JSON testers. * auto-configuration of JSON testers.
* *
* @author Phillip Webb * @author Phillip Webb
* @since 4.0.0 * @since 1.4.0
*/ */
@Target(ElementType.TYPE) @Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)

View File

@ -0,0 +1,42 @@
/*
* Copyright 2012-present 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.test.autoconfigure.json;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Conditional;
/**
* {@link Conditional @Conditional} that checks if JSON testers are enabled.
*
* @author Phillip Webb
* @since 4.0.0
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@ConditionalOnBooleanProperty("spring.test.jsontesters.enabled")
@ConditionalOnClass(name = "org.assertj.core.api.Assert")
public @interface ConditionalOnJsonTesters {
}

View File

@ -0,0 +1,57 @@
/*
* Copyright 2012-present 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.test.autoconfigure.json;
import java.lang.reflect.Method;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.ExecutableMode;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.ReflectionHints;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.boot.test.json.AbstractJsonMarshalTester;
import org.springframework.core.ResolvableType;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
/**
* Base class for {@link AbstractJsonMarshalTester} runtime hints.
*
* @author Phillip Webb
* @since 4.0.0
*/
@SuppressWarnings("rawtypes")
public abstract class JsonMarshalTesterRuntimeHints implements RuntimeHintsRegistrar {
private final Class<? extends AbstractJsonMarshalTester> tester;
protected JsonMarshalTesterRuntimeHints(Class<? extends AbstractJsonMarshalTester> tester) {
this.tester = tester;
}
@Override
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
ReflectionHints reflection = hints.reflection();
reflection.registerType(this.tester, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
Method method = ReflectionUtils.findMethod(this.tester, "initialize", Class.class, ResolvableType.class);
Assert.state(method != null, "'method' must not be null");
reflection.registerMethod(method, ExecutableMode.INVOKE);
}
}

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test.autoconfigure; package org.springframework.boot.test.autoconfigure.json;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
@ -27,11 +27,11 @@ import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.json.test.GsonTester;
import org.springframework.boot.json.test.JacksonTester;
import org.springframework.boot.json.test.JsonbTester;
import org.springframework.boot.test.autoconfigure.OverrideAutoConfiguration; import org.springframework.boot.test.autoconfigure.OverrideAutoConfiguration;
import org.springframework.boot.test.context.filter.annotation.TypeExcludeFilters; import org.springframework.boot.test.context.filter.annotation.TypeExcludeFilters;
import org.springframework.boot.test.json.GsonTester;
import org.springframework.boot.test.json.JacksonTester;
import org.springframework.boot.test.json.JsonbTester;
import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.core.annotation.AliasFor; import org.springframework.core.annotation.AliasFor;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
@ -64,7 +64,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
* @author Artsiom Yudovin * @author Artsiom Yudovin
* @see AutoConfigureJson * @see AutoConfigureJson
* @see AutoConfigureJsonTesters * @see AutoConfigureJsonTesters
* @since 4.0.0 * @since 1.4.0
*/ */
@Target(ElementType.TYPE) @Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test.autoconfigure; package org.springframework.boot.test.autoconfigure.json;
import org.springframework.boot.test.autoconfigure.TestSliceTestContextBootstrapper; import org.springframework.boot.test.autoconfigure.TestSliceTestContextBootstrapper;
import org.springframework.test.context.TestContextBootstrapper; import org.springframework.test.context.TestContextBootstrapper;

View File

@ -0,0 +1,75 @@
/*
* Copyright 2012-present 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.test.autoconfigure.json;
import java.lang.reflect.Constructor;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.util.ReflectionUtils;
/**
* {@link FactoryBean} used to create JSON Tester instances.
*
* @param <T> the object type
* @param <M> the marshaller type
* @author Phillip Webb
* @since 4.0.0
*/
public final class JsonTesterFactoryBean<T, M> implements FactoryBean<T> {
private final Class<?> objectType;
private final @Nullable M marshaller;
public JsonTesterFactoryBean(Class<?> objectType, @Nullable M marshaller) {
this.objectType = objectType;
this.marshaller = marshaller;
}
@Override
public boolean isSingleton() {
return false;
}
@Override
@SuppressWarnings("unchecked")
public T getObject() throws Exception {
if (this.marshaller == null) {
Constructor<?> constructor = this.objectType.getDeclaredConstructor();
ReflectionUtils.makeAccessible(constructor);
return (T) BeanUtils.instantiateClass(constructor);
}
Constructor<?>[] constructors = this.objectType.getDeclaredConstructors();
for (Constructor<?> constructor : constructors) {
if (constructor.getParameterCount() == 1
&& constructor.getParameterTypes()[0].isInstance(this.marshaller)) {
ReflectionUtils.makeAccessible(constructor);
return (T) BeanUtils.instantiateClass(constructor, this.marshaller);
}
}
throw new IllegalStateException(this.objectType + " does not have a usable constructor");
}
@Override
public Class<?> getObjectType() {
return this.objectType;
}
}

View File

@ -0,0 +1,112 @@
/*
* Copyright 2012-present 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.test.autoconfigure.json;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.ExecutableMode;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.ReflectionHints;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.test.json.AbstractJsonMarshalTester;
import org.springframework.boot.test.json.BasicJsonTester;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ImportRuntimeHints;
import org.springframework.context.annotation.Scope;
import org.springframework.core.ResolvableType;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
/**
* Auto-configuration for Json testers.
*
* @author Phillip Webb
* @author Eddú Meléndez
* @since 1.4.0
* @see AutoConfigureJsonTesters
*/
@AutoConfiguration
@ConditionalOnJsonTesters
public final class JsonTestersAutoConfiguration {
@Bean
static JsonMarshalTestersBeanPostProcessor jsonMarshalTestersBeanPostProcessor() {
return new JsonMarshalTestersBeanPostProcessor();
}
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@ImportRuntimeHints(BasicJsonTesterRuntimeHints.class)
FactoryBean<BasicJsonTester> basicJsonTesterFactoryBean() {
return new JsonTesterFactoryBean<BasicJsonTester, Void>(BasicJsonTester.class, null);
}
/**
* {@link BeanPostProcessor} used to initialize JSON testers.
*/
static class JsonMarshalTestersBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
ReflectionUtils.doWithFields(bean.getClass(), (field) -> processField(bean, field));
return bean;
}
private void processField(Object bean, Field field) {
if (AbstractJsonMarshalTester.class.isAssignableFrom(field.getType())) {
initializeTester(bean, field, bean.getClass(), ResolvableType.forField(field).getGeneric());
}
else if (BasicJsonTester.class.isAssignableFrom(field.getType())) {
initializeTester(bean, field, bean.getClass());
}
}
private void initializeTester(Object bean, Field field, Object... args) {
ReflectionUtils.makeAccessible(field);
Object tester = ReflectionUtils.getField(field, bean);
if (tester != null) {
ReflectionTestUtils.invokeMethod(tester, "initialize", args);
}
}
}
static class BasicJsonTesterRuntimeHints implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
ReflectionHints reflection = hints.reflection();
reflection.registerType(BasicJsonTester.class, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
Method method = ReflectionUtils.findMethod(BasicJsonTester.class, "initialize", Class.class);
Assert.state(method != null, "'method' must not be null");
reflection.registerMethod(method, ExecutableMode.INVOKE);
}
}
}

View File

@ -14,16 +14,10 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test.autoconfigure; package org.springframework.boot.test.autoconfigure.json;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import org.springframework.boot.context.TypeExcludeFilter; import org.springframework.boot.context.TypeExcludeFilter;
import org.springframework.boot.jackson.JsonComponent;
import org.springframework.boot.test.context.filter.annotation.StandardAnnotationCustomizableTypeExcludeFilter; import org.springframework.boot.test.context.filter.annotation.StandardAnnotationCustomizableTypeExcludeFilter;
import org.springframework.util.ClassUtils;
/** /**
* {@link TypeExcludeFilter} for {@link JsonTest @JsonTest}. * {@link TypeExcludeFilter} for {@link JsonTest @JsonTest}.
@ -32,29 +26,8 @@ import org.springframework.util.ClassUtils;
*/ */
class JsonTypeExcludeFilter extends StandardAnnotationCustomizableTypeExcludeFilter<JsonTest> { class JsonTypeExcludeFilter extends StandardAnnotationCustomizableTypeExcludeFilter<JsonTest> {
private static final String JACKSON_MODULE = "tools.jackson.databind.JacksonModule";
private static final Set<Class<?>> KNOWN_INCLUDES;
static {
Set<Class<?>> includes = new LinkedHashSet<>();
try {
includes.add(ClassUtils.forName(JACKSON_MODULE, null));
}
catch (Exception ex) {
// Ignore
}
includes.add(JsonComponent.class);
KNOWN_INCLUDES = Collections.unmodifiableSet(includes);
}
JsonTypeExcludeFilter(Class<?> testClass) { JsonTypeExcludeFilter(Class<?> testClass) {
super(testClass); super(testClass);
} }
@Override
protected Set<Class<?>> getKnownIncludes() {
return KNOWN_INCLUDES;
}
} }

View File

@ -18,6 +18,6 @@
* Auto-configuration for JSON tests. * Auto-configuration for JSON tests.
*/ */
@NullMarked @NullMarked
package org.springframework.boot.json.test.autoconfigure; package org.springframework.boot.test.autoconfigure.json;
import org.jspecify.annotations.NullMarked; import org.jspecify.annotations.NullMarked;

View File

@ -1,5 +1,11 @@
{ {
"properties": [ "properties": [
{
"name": "spring.test.jsontesters.enabled",
"type": "java.lang.Boolean",
"description": "Whether auto-configuration of JSON testers is enabled.",
"defaultValue": "true"
},
{ {
"name": "spring.test.print-condition-evaluation-report", "name": "spring.test.print-condition-evaluation-report",
"type": "java.lang.Boolean", "type": "java.lang.Boolean",

View File

@ -0,0 +1 @@
org.springframework.boot.test.autoconfigure.json.JsonTestersAutoConfiguration

View File

@ -17,7 +17,7 @@
package org.springframework.boot.json.test.autoconfigure.app; package org.springframework.boot.json.test.autoconfigure.app;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.json.test.autoconfigure.JsonTest; import org.springframework.boot.test.autoconfigure.json.JsonTest;
/** /**
* Example {@link SpringBootApplication @SpringBootApplication} for use with * Example {@link SpringBootApplication @SpringBootApplication} for use with

View File

@ -0,0 +1,30 @@
/*
* Copyright 2012-present 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.test.autoconfigure.json;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* Example {@link SpringBootApplication @SpringBootApplication} for use with
* {@link JsonTest @JsonTest} tests.
*
* @author Phillip Webb
*/
@SpringBootApplication
public class ExampleJsonApplication {
}

View File

@ -0,0 +1,47 @@
/*
* Copyright 2012-present 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.test.autoconfigure.json;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.json.test.autoconfigure.app.ExampleJsonApplication;
import org.springframework.boot.test.json.BasicJsonTester;
import org.springframework.test.context.ContextConfiguration;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests for {@link JsonTest @JsonTest}.
*
* @author Phillip Webb
* @author Madhura Bhave
* @author Eddú Meléndez
*/
@JsonTest
@ContextConfiguration(classes = ExampleJsonApplication.class)
class JsonTestIntegrationTests {
@Autowired
private BasicJsonTester basicJson;
@Test
void basicJson() {
assertThat(this.basicJson.from("{\"a\":\"b\"}")).hasJsonPathStringValue("@.a");
}
}

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test.autoconfigure; package org.springframework.boot.test.autoconfigure.json;
import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;

View File

@ -14,17 +14,13 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test.autoconfigure; package org.springframework.boot.test.autoconfigure.json;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.json.test.BasicJsonTester;
import org.springframework.boot.json.test.GsonTester;
import org.springframework.boot.json.test.JacksonTester;
import org.springframework.boot.json.test.JsonbTester;
import org.springframework.boot.json.test.autoconfigure.app.ExampleBasicObject;
import org.springframework.boot.json.test.autoconfigure.app.ExampleJsonApplication; import org.springframework.boot.json.test.autoconfigure.app.ExampleJsonApplication;
import org.springframework.boot.test.json.BasicJsonTester;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -43,33 +39,9 @@ class JsonTestWithAutoConfigureJsonTestersTests {
@Autowired(required = false) @Autowired(required = false)
private BasicJsonTester basicJson; private BasicJsonTester basicJson;
@Autowired(required = false)
private JacksonTester<ExampleBasicObject> jacksonTester;
@Autowired(required = false)
private GsonTester<ExampleBasicObject> gsonTester;
@Autowired(required = false)
private JsonbTester<ExampleBasicObject> jsonbTester;
@Test @Test
void basicJson() { void basicJson() {
assertThat(this.basicJson).isNull(); assertThat(this.basicJson).isNull();
} }
@Test
void jackson() {
assertThat(this.jacksonTester).isNull();
}
@Test
void gson() {
assertThat(this.gsonTester).isNull();
}
@Test
void jsonb() {
assertThat(this.jsonbTester).isNull();
}
} }

View File

@ -0,0 +1,52 @@
/*
* Copyright 2012-present 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.test.autoconfigure.json;
import org.junit.jupiter.api.Test;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.predicate.ReflectionHintsPredicates;
import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
import org.springframework.aot.test.generate.TestGenerationContext;
import org.springframework.boot.test.json.BasicJsonTester;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.aot.ApplicationContextAotGenerator;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link JsonTestersAutoConfiguration}.
*
* @author Andy Wilkinson
*/
class JsonTestersAutoConfigurationTests {
@Test
void basicJsonTesterHintsAreContributed() {
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext()) {
TestPropertyValues.of("spring.test.jsontesters.enabled=true").applyTo(context);
context.register(JsonTestersAutoConfiguration.class);
TestGenerationContext generationContext = new TestGenerationContext();
new ApplicationContextAotGenerator().processAheadOfTime(context, generationContext);
RuntimeHints runtimeHints = generationContext.getRuntimeHints();
ReflectionHintsPredicates reflection = RuntimeHintsPredicates.reflection();
assertThat(reflection.onType(BasicJsonTester.class)).accepts(runtimeHints);
}
}
}

View File

@ -14,18 +14,14 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test.autoconfigure; package org.springframework.boot.test.autoconfigure.json;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.json.test.BasicJsonTester;
import org.springframework.boot.json.test.GsonTester;
import org.springframework.boot.json.test.JacksonTester;
import org.springframework.boot.json.test.JsonbTester;
import org.springframework.boot.json.test.autoconfigure.app.ExampleBasicObject;
import org.springframework.boot.json.test.autoconfigure.app.ExampleJsonApplication; import org.springframework.boot.json.test.autoconfigure.app.ExampleJsonApplication;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.json.BasicJsonTester;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -44,21 +40,9 @@ class SpringBootTestWithAutoConfigureJsonTestersTests {
@Autowired @Autowired
private BasicJsonTester basicJson; private BasicJsonTester basicJson;
@Autowired
private JacksonTester<ExampleBasicObject> jacksonTester;
@Autowired
private GsonTester<ExampleBasicObject> gsonTester;
@Autowired
private JsonbTester<ExampleBasicObject> jsonbTester;
@Test @Test
void contextLoads() { void contextLoads() {
assertThat(this.basicJson).isNotNull(); assertThat(this.basicJson).isNotNull();
assertThat(this.jacksonTester).isNotNull();
assertThat(this.jsonbTester).isNotNull();
assertThat(this.gsonTester).isNotNull();
} }
} }

View File

@ -27,6 +27,10 @@ dependencies {
api(project(":core:spring-boot")) api(project(":core:spring-boot"))
api("org.springframework:spring-test") api("org.springframework:spring-test")
optional("tools.jackson.core:jackson-databind")
optional("com.google.code.gson:gson")
optional("com.jayway.jsonpath:json-path")
optional("jakarta.json.bind:jakarta.json.bind-api")
optional("jakarta.servlet:jakarta.servlet-api") optional("jakarta.servlet:jakarta.servlet-api")
optional("junit:junit") optional("junit:junit")
optional("org.assertj:assertj-core") optional("org.assertj:assertj-core")
@ -34,11 +38,13 @@ dependencies {
optional("org.hamcrest:hamcrest-library") optional("org.hamcrest:hamcrest-library")
optional("org.junit.jupiter:junit-jupiter-api") optional("org.junit.jupiter:junit-jupiter-api")
optional("org.mockito:mockito-core") optional("org.mockito:mockito-core")
optional("org.skyscreamer:jsonassert")
optional("org.springframework:spring-web") optional("org.springframework:spring-web")
testImplementation(project(":test-support:spring-boot-test-support")) testImplementation(project(":test-support:spring-boot-test-support"))
testImplementation("ch.qos.logback:logback-classic") testImplementation("ch.qos.logback:logback-classic")
testImplementation("com.google.code.gson:gson") testImplementation("com.google.code.gson:gson")
testImplementation("org.eclipse:yasson")
testImplementation("org.jetbrains.kotlin:kotlin-reflect") testImplementation("org.jetbrains.kotlin:kotlin-reflect")
testImplementation("org.jetbrains.kotlin:kotlin-stdlib") testImplementation("org.jetbrains.kotlin:kotlin-stdlib")
testImplementation("org.slf4j:slf4j-api") testImplementation("org.slf4j:slf4j-api")

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test; package org.springframework.boot.test.json;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.Closeable; import java.io.Closeable;

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test; package org.springframework.boot.test.json;
import java.io.File; import java.io.File;
import java.io.InputStream; import java.io.InputStream;

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test; package org.springframework.boot.test.json;
import java.net.URL; import java.net.URL;
import java.util.Collections; import java.util.Collections;

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test; package org.springframework.boot.test.json;
import java.io.IOException; import java.io.IOException;
import java.io.Reader; import java.io.Reader;

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test; package org.springframework.boot.test.json;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test; package org.springframework.boot.test.json;
import com.jayway.jsonpath.Configuration; import com.jayway.jsonpath.Configuration;
import org.assertj.core.api.AssertProvider; import org.assertj.core.api.AssertProvider;

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test; package org.springframework.boot.test.json;
import java.io.File; import java.io.File;
import java.io.InputStream; import java.io.InputStream;

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test; package org.springframework.boot.test.json;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.File; import java.io.File;

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test; package org.springframework.boot.test.json;
import java.io.IOException; import java.io.IOException;
import java.io.Reader; import java.io.Reader;

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test; package org.springframework.boot.test.json;
import org.assertj.core.api.AssertProvider; import org.assertj.core.api.AssertProvider;
import org.jspecify.annotations.Nullable; import org.jspecify.annotations.Nullable;

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test; package org.springframework.boot.test.json;
import org.assertj.core.api.AbstractMapAssert; import org.assertj.core.api.AbstractMapAssert;
import org.assertj.core.api.AbstractObjectArrayAssert; import org.assertj.core.api.AbstractObjectArrayAssert;

View File

@ -18,6 +18,6 @@
* Support for testing JSON. * Support for testing JSON.
*/ */
@NullMarked @NullMarked
package org.springframework.boot.json.test; package org.springframework.boot.test.json;
import org.jspecify.annotations.NullMarked; import org.jspecify.annotations.NullMarked;

View File

@ -3,8 +3,8 @@ org.springframework.test.context.ContextCustomizerFactory=\
org.springframework.boot.test.context.ImportsContextCustomizerFactory,\ org.springframework.boot.test.context.ImportsContextCustomizerFactory,\
org.springframework.boot.test.context.PropertyMappingContextCustomizerFactory,\ org.springframework.boot.test.context.PropertyMappingContextCustomizerFactory,\
org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizerFactory,\ org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizerFactory,\
org.springframework.boot.test.context.filter.annotation.TypeExcludeFiltersContextCustomizerFactory org.springframework.boot.test.context.filter.annotation.TypeExcludeFiltersContextCustomizerFactory,\
org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory
# Application Context Initializers # Application Context Initializers
org.springframework.context.ApplicationContextInitializer=\ org.springframework.context.ApplicationContextInitializer=\

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test; package org.springframework.boot.test.json;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.File; import java.io.File;

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test; package org.springframework.boot.test.json;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.File; import java.io.File;

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test; package org.springframework.boot.test.json;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test; package org.springframework.boot.test.json;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test; package org.springframework.boot.test.json;
import com.fasterxml.jackson.annotation.JsonView; import com.fasterxml.jackson.annotation.JsonView;

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test; package org.springframework.boot.test.json;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test; package org.springframework.boot.test.json;
import java.util.List; import java.util.List;

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test; package org.springframework.boot.test.json;
import java.io.Reader; import java.io.Reader;
import java.io.StringReader; import java.io.StringReader;

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test; package org.springframework.boot.test.json;
import java.util.List; import java.util.List;

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test; package org.springframework.boot.test.json;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.File; import java.io.File;

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test; package org.springframework.boot.test.json;
import com.jayway.jsonpath.Configuration; import com.jayway.jsonpath.Configuration;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test; package org.springframework.boot.test.json;
import java.util.List; import java.util.List;

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test; package org.springframework.boot.test.json;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test; package org.springframework.boot.test.json;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;

View File

@ -115,7 +115,6 @@ dependencies {
implementation(project(path: ":module:spring-boot-jpa")) implementation(project(path: ":module:spring-boot-jpa"))
implementation(project(path: ":module:spring-boot-jms")) implementation(project(path: ":module:spring-boot-jms"))
implementation(project(path: ":module:spring-boot-jsonb")) implementation(project(path: ":module:spring-boot-jsonb"))
implementation(project(path: ":module:spring-boot-json-test"))
implementation(project(path: ":module:spring-boot-ldap")) implementation(project(path: ":module:spring-boot-ldap"))
implementation(project(path: ":module:spring-boot-micrometer-metrics")) implementation(project(path: ":module:spring-boot-micrometer-metrics"))
implementation(project(path: ":module:spring-boot-persistence")) implementation(project(path: ":module:spring-boot-persistence"))

View File

@ -292,7 +292,7 @@ You can use this combination if you are not interested in "`slicing`" your appli
[[testing.spring-boot-applications.json-tests]] [[testing.spring-boot-applications.json-tests]]
== Auto-configured JSON Tests == Auto-configured JSON Tests
To test that object JSON serialization and deserialization is working as expected, you can use the javadoc:org.springframework.boot.json.test.autoconfigure.JsonTest[format=annotation] annotation from the `spring-boot-json-test` module. To test that object JSON serialization and deserialization is working as expected, you can use the javadoc:org.springframework.boot.json.test.autoconfigure.JsonTest[format=annotation] annotation from the `spring-boot-test-autoconfigure` module.
javadoc:org.springframework.boot.json.test.autoconfigure.JsonTest[format=annotation] auto-configures the available supported JSON mapper, which can be one of the following libraries: javadoc:org.springframework.boot.json.test.autoconfigure.JsonTest[format=annotation] auto-configures the available supported JSON mapper, which can be one of the following libraries:
* Jackson javadoc:tools.jackson.databind.JsonMapper[], any javadoc:org.springframework.boot.jackson.JsonComponent[format=annotation] beans and any Jackson javadoc:tools.jackson.databind.JacksonModule[] * Jackson javadoc:tools.jackson.databind.JsonMapper[], any javadoc:org.springframework.boot.jackson.JsonComponent[format=annotation] beans and any Jackson javadoc:tools.jackson.databind.JacksonModule[]

View File

@ -52,9 +52,6 @@ Spring Boot offers several focused, feature-specific `-test` modules:
|`spring-boot-jpa-test` |`spring-boot-jpa-test`
|Testing applications that use JPA. |Testing applications that use JPA.
|`spring-boot-json-test`
|Testing applications that use JSON. Provides the `@JsonTest` test slice.
|`spring-boot-micrometer-metrics-test` |`spring-boot-micrometer-metrics-test`
|Testing applications that use Micrometer Metrics. |Testing applications that use Micrometer Metrics.

View File

@ -19,8 +19,8 @@ package org.springframework.boot.docs.testing.springbootapplications.jsontests;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.json.test.JacksonTester; import org.springframework.boot.test.autoconfigure.json.JsonTest;
import org.springframework.boot.json.test.autoconfigure.JsonTest; import org.springframework.boot.test.json.JacksonTester;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.within; import static org.assertj.core.api.Assertions.within;

View File

@ -19,8 +19,8 @@ package org.springframework.boot.docs.testing.springbootapplications.jsontests;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.json.test.JacksonTester; import org.springframework.boot.test.autoconfigure.json.JsonTest;
import org.springframework.boot.json.test.autoconfigure.JsonTest; import org.springframework.boot.test.json.JacksonTester;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;

View File

@ -21,8 +21,8 @@ import org.assertj.core.api.Assertions.within
import org.assertj.core.api.ThrowingConsumer import org.assertj.core.api.ThrowingConsumer
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.json.test.autoconfigure.JsonTest import org.springframework.boot.test.autoconfigure.json.JsonTest
import org.springframework.boot.json.test.JacksonTester import org.springframework.boot.test.json.JacksonTester
@JsonTest @JsonTest
class MyJsonAssertJTests(@Autowired val json: JacksonTester<SomeObject>) { class MyJsonAssertJTests(@Autowired val json: JacksonTester<SomeObject>) {

View File

@ -19,8 +19,8 @@ package org.springframework.boot.docs.testing.springbootapplications.jsontests
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.json.test.autoconfigure.JsonTest import org.springframework.boot.test.autoconfigure.json.JsonTest
import org.springframework.boot.json.test.JacksonTester import org.springframework.boot.test.json.JacksonTester
@JsonTest @JsonTest
class MyJsonTests(@Autowired val json: JacksonTester<VehicleDetails>) { class MyJsonTests(@Autowired val json: JacksonTester<VehicleDetails>) {

View File

@ -65,7 +65,6 @@ dependencies {
testImplementation(project(":core:spring-boot-test")) testImplementation(project(":core:spring-boot-test"))
testImplementation(project(":module:spring-boot-jackson")) testImplementation(project(":module:spring-boot-jackson"))
testImplementation(project(":module:spring-boot-jsonb")) testImplementation(project(":module:spring-boot-jsonb"))
testImplementation(project(":module:spring-boot-json-test"))
testImplementation(project(":test-support:spring-boot-test-support")) testImplementation(project(":test-support:spring-boot-test-support"))
testImplementation("io.micrometer:micrometer-observation-test") testImplementation("io.micrometer:micrometer-observation-test")
testImplementation("io.projectreactor:reactor-test") testImplementation("io.projectreactor:reactor-test")

View File

@ -27,7 +27,7 @@ import org.junit.jupiter.api.Test;
import tools.jackson.databind.JavaType; import tools.jackson.databind.JavaType;
import tools.jackson.databind.ObjectMapper; import tools.jackson.databind.ObjectMapper;
import org.springframework.boot.json.test.BasicJsonTester; import org.springframework.boot.test.json.BasicJsonTester;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;

View File

@ -31,7 +31,6 @@ dependencies {
implementation(project(":module:spring-boot-jackson")) implementation(project(":module:spring-boot-jackson"))
optional(project(":core:spring-boot-autoconfigure")) optional(project(":core:spring-boot-autoconfigure"))
optional(project(":module:spring-boot-json-test"))
optional(project(":module:spring-boot-validation")) optional(project(":module:spring-boot-validation"))
optional(project(":module:spring-boot-webclient")) optional(project(":module:spring-boot-webclient"))
optional(project(":module:spring-boot-webflux-test")) optional(project(":module:spring-boot-webflux-test"))

View File

@ -29,8 +29,8 @@ import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.graphql.test.autoconfigure.tester.AutoConfigureGraphQlTester; import org.springframework.boot.graphql.test.autoconfigure.tester.AutoConfigureGraphQlTester;
import org.springframework.boot.graphql.test.autoconfigure.tester.AutoConfigureHttpGraphQlTester; import org.springframework.boot.graphql.test.autoconfigure.tester.AutoConfigureHttpGraphQlTester;
import org.springframework.boot.json.test.autoconfigure.AutoConfigureJson;
import org.springframework.boot.test.autoconfigure.OverrideAutoConfiguration; import org.springframework.boot.test.autoconfigure.OverrideAutoConfiguration;
import org.springframework.boot.test.autoconfigure.json.AutoConfigureJson;
import org.springframework.boot.test.context.filter.annotation.TypeExcludeFilters; import org.springframework.boot.test.context.filter.annotation.TypeExcludeFilters;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import org.springframework.core.annotation.AliasFor; import org.springframework.core.annotation.AliasFor;

View File

@ -30,8 +30,8 @@ dependencies {
api("com.google.code.gson:gson") api("com.google.code.gson:gson")
optional(project(":core:spring-boot-autoconfigure")) optional(project(":core:spring-boot-autoconfigure"))
optional(project(":core:spring-boot-test-autoconfigure"))
testImplementation(project(":core:spring-boot-test"))
testImplementation(project(":test-support:spring-boot-test-support")) testImplementation(project(":test-support:spring-boot-test-support"))
testRuntimeOnly("ch.qos.logback:logback-classic") testRuntimeOnly("ch.qos.logback:logback-classic")

View File

@ -0,0 +1,59 @@
/*
* Copyright 2012-present 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.gson.autoconfigure;
import com.google.gson.Gson;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.test.autoconfigure.TestAutoConfiguration;
import org.springframework.boot.test.autoconfigure.json.ConditionalOnJsonTesters;
import org.springframework.boot.test.autoconfigure.json.JsonMarshalTesterRuntimeHints;
import org.springframework.boot.test.autoconfigure.json.JsonTesterFactoryBean;
import org.springframework.boot.test.json.GsonTester;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ImportRuntimeHints;
import org.springframework.context.annotation.Scope;
/**
* {@link EnableAutoConfiguration Auto-configuration} for {@link GsonTester}.
*
* @author Phjllip Webb
*/
@TestAutoConfiguration(after = GsonAutoConfiguration.class)
@ConditionalOnJsonTesters
final class GsonTesterAutoConfiguration {
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@ConditionalOnBean(Gson.class)
@ImportRuntimeHints(GsonTesterRuntimeHints.class)
FactoryBean<GsonTester<?>> gsonTesterFactoryBean(Gson gson) {
return new JsonTesterFactoryBean<>(GsonTester.class, gson);
}
static class GsonTesterRuntimeHints extends JsonMarshalTesterRuntimeHints {
GsonTesterRuntimeHints() {
super(GsonTester.class);
}
}
}

View File

@ -0,0 +1,2 @@
org.springframework.boot.gson.autoconfigure.GsonAutoConfiguration
org.springframework.boot.gson.autoconfigure.GsonTesterAutoConfiguration

View File

@ -0,0 +1,54 @@
/*
* Copyright 2012-present 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.gson.autoconfigure;
import org.junit.jupiter.api.Test;
import org.springframework.aot.hint.predicate.ReflectionHintsPredicates;
import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
import org.springframework.aot.test.generate.TestGenerationContext;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.autoconfigure.json.JsonTestersAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.test.json.GsonTester;
import org.springframework.context.aot.ApplicationContextAotGenerator;
import org.springframework.context.support.GenericApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link GsonTesterAutoConfiguration}.
*
* @author Andy Wilkinson
*/
class GsonTesterAutoConfigurationTests {
private final ApplicationContextRunner runner = new ApplicationContextRunner().withConfiguration(AutoConfigurations
.of(JsonTestersAutoConfiguration.class, GsonAutoConfiguration.class, GsonTesterAutoConfiguration.class));
@Test
void hintsAreContributed() {
this.runner.withPropertyValues("spring.test.jsontesters.enabled=true").prepare((context) -> {
TestGenerationContext generationContext = new TestGenerationContext();
new ApplicationContextAotGenerator().processAheadOfTime(
(GenericApplicationContext) context.getSourceApplicationContext(), generationContext);
ReflectionHintsPredicates hints = RuntimeHintsPredicates.reflection();
assertThat(hints.onType(GsonTester.class)).accepts(generationContext.getRuntimeHints());
});
}
}

View File

@ -0,0 +1,30 @@
/*
* Copyright 2012-present 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.gson.autoconfigure.jsontest;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.autoconfigure.json.JsonTest;
/**
* Application for testing of {@link JsonTest @JsonTest}.
*
* @author Andy Wilkinson
*/
@SpringBootApplication
class JsonTestApplication {
}

View File

@ -0,0 +1,51 @@
/*
* Copyright 2012-present 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.gson.autoconfigure.jsontest;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.gson.autoconfigure.jsontest.app.ExampleBasicObject;
import org.springframework.boot.gson.autoconfigure.jsontest.app.ExampleJsonApplication;
import org.springframework.boot.test.autoconfigure.json.JsonTest;
import org.springframework.boot.test.json.GsonTester;
import org.springframework.test.context.ContextConfiguration;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests for {@link JsonTest @JsonTest}.
*
* @author Phillip Webb
* @author Madhura Bhave
* @author Eddú Meléndez
*/
@JsonTest
@ContextConfiguration(classes = ExampleJsonApplication.class)
class JsonTestIntegrationTests {
@Autowired
private GsonTester<ExampleBasicObject> gsonJson;
@Test
void gson() throws Exception {
ExampleBasicObject object = new ExampleBasicObject();
object.setValue("spring");
assertThat(this.gsonJson.write(object)).isEqualToJson("example.json");
}
}

View File

@ -0,0 +1,50 @@
/*
* Copyright 2012-present 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.gson.autoconfigure.jsontest;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.gson.autoconfigure.jsontest.app.ExampleBasicObject;
import org.springframework.boot.gson.autoconfigure.jsontest.app.ExampleJsonApplication;
import org.springframework.boot.test.autoconfigure.json.AutoConfigureJsonTesters;
import org.springframework.boot.test.autoconfigure.json.JsonTest;
import org.springframework.boot.test.json.GsonTester;
import org.springframework.test.context.ContextConfiguration;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests for {@link JsonTest @JsonTest} with
* {@link AutoConfigureJsonTesters @AutoConfigureJsonTesters}.
*
* @author Phillip Webb
*/
@JsonTest
@AutoConfigureJsonTesters(enabled = false)
@ContextConfiguration(classes = ExampleJsonApplication.class)
class JsonTestWithAutoConfigureJsonTestersTests {
@Autowired(required = false)
private GsonTester<ExampleBasicObject> gsonTester;
@Test
void gson() {
assertThat(this.gsonTester).isNull();
}
}

View File

@ -0,0 +1,50 @@
/*
* Copyright 2012-present 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.gson.autoconfigure.jsontest;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.gson.autoconfigure.jsontest.app.ExampleBasicObject;
import org.springframework.boot.gson.autoconfigure.jsontest.app.ExampleJsonApplication;
import org.springframework.boot.test.autoconfigure.json.AutoConfigureJsonTesters;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.json.GsonTester;
import org.springframework.test.context.ContextConfiguration;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests for {@link SpringBootTest @SpringBootTest} with
* {@link AutoConfigureJsonTesters @AutoConfigureJsonTesters}.
*
* @author Andy Wilkinson
*/
@SpringBootTest
@AutoConfigureJsonTesters
@ContextConfiguration(classes = ExampleJsonApplication.class)
class SpringBootTestWithAutoConfigureJsonTestersTests {
@Autowired
private GsonTester<ExampleBasicObject> gsonTester;
@Test
void contextLoads() {
assertThat(this.gsonTester).isNotNull();
}
}

View File

@ -0,0 +1,49 @@
/*
* Copyright 2012-present 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.gson.autoconfigure.jsontest.app;
/**
* Example object to read/write as JSON.
*
* @author Phillip Webb
*/
public class ExampleBasicObject {
private String value;
public String getValue() {
return this.value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public boolean equals(Object obj) {
if (obj != null && obj.getClass() == getClass()) {
return this.value.equals(((ExampleBasicObject) obj).value);
}
return false;
}
@Override
public int hashCode() {
return this.value.hashCode();
}
}

View File

@ -0,0 +1,31 @@
/*
* Copyright 2012-present 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.gson.autoconfigure.jsontest.app;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.autoconfigure.json.JsonTest;
/**
* Example {@link SpringBootApplication @SpringBootApplication} for use with
* {@link JsonTest @JsonTest} tests.
*
* @author Phillip Webb
*/
@SpringBootApplication
public class ExampleJsonApplication {
}

View File

@ -29,6 +29,7 @@ dependencies {
api("tools.jackson.core:jackson-databind") api("tools.jackson.core:jackson-databind")
optional(project(":core:spring-boot-autoconfigure")) optional(project(":core:spring-boot-autoconfigure"))
optional(project(":core:spring-boot-test-autoconfigure"))
optional("org.springframework:spring-web") optional("org.springframework:spring-web")
optional("tools.jackson.dataformat:jackson-dataformat-cbor") optional("tools.jackson.dataformat:jackson-dataformat-cbor")
optional("tools.jackson.dataformat:jackson-dataformat-xml") optional("tools.jackson.dataformat:jackson-dataformat-xml")

View File

@ -0,0 +1,60 @@
/*
* Copyright 2012-present 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.jackson.autoconfigure;
import tools.jackson.databind.json.JsonMapper;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.test.autoconfigure.TestAutoConfiguration;
import org.springframework.boot.test.autoconfigure.json.ConditionalOnJsonTesters;
import org.springframework.boot.test.autoconfigure.json.JsonMarshalTesterRuntimeHints;
import org.springframework.boot.test.autoconfigure.json.JsonTesterFactoryBean;
import org.springframework.boot.test.json.GsonTester;
import org.springframework.boot.test.json.JacksonTester;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ImportRuntimeHints;
import org.springframework.context.annotation.Scope;
/**
* {@link EnableAutoConfiguration Auto-configuration} for {@link GsonTester}.
*
* @author Phjllip Webb
*/
@TestAutoConfiguration(after = JacksonAutoConfiguration.class)
@ConditionalOnJsonTesters
final class JacksonTesterAutoConfiguration {
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@ConditionalOnBean(JsonMapper.class)
@ImportRuntimeHints(JacksonTesterRuntimeHints.class)
FactoryBean<JacksonTester<?>> jacksonTesterFactoryBean(JsonMapper mapper) {
return new JsonTesterFactoryBean<>(JacksonTester.class, mapper);
}
static class JacksonTesterRuntimeHints extends JsonMarshalTesterRuntimeHints {
JacksonTesterRuntimeHints() {
super(JacksonTester.class);
}
}
}

View File

@ -0,0 +1,2 @@
org.springframework.boot.jackson.autoconfigure.JacksonAutoConfiguration
org.springframework.boot.jackson.autoconfigure.JacksonTesterAutoConfiguration

View File

@ -0,0 +1,2 @@
org.springframework.boot.jackson.JsonComponent
tools.jackson.databind.JacksonModule

View File

@ -0,0 +1,54 @@
/*
* Copyright 2012-present 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.jackson.autoconfigure;
import org.junit.jupiter.api.Test;
import org.springframework.aot.hint.predicate.ReflectionHintsPredicates;
import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
import org.springframework.aot.test.generate.TestGenerationContext;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.autoconfigure.json.JsonTestersAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.test.json.JacksonTester;
import org.springframework.context.aot.ApplicationContextAotGenerator;
import org.springframework.context.support.GenericApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link JsonTestersAutoConfiguration}.
*
* @author Andy Wilkinson
*/
class JacksonTesterAutoConfigurationTests {
private final ApplicationContextRunner runner = new ApplicationContextRunner().withConfiguration(AutoConfigurations
.of(JsonTestersAutoConfiguration.class, JacksonAutoConfiguration.class, JacksonTesterAutoConfiguration.class));
@Test
void hintsAreContributed() {
this.runner.withPropertyValues("spring.test.jsontesters.enabled=true").prepare((context) -> {
TestGenerationContext generationContext = new TestGenerationContext();
new ApplicationContextAotGenerator().processAheadOfTime(
(GenericApplicationContext) context.getSourceApplicationContext(), generationContext);
ReflectionHintsPredicates hints = RuntimeHintsPredicates.reflection();
assertThat(hints.onType(JacksonTester.class)).accepts(generationContext.getRuntimeHints());
});
}
}

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test.autoconfigure; package org.springframework.boot.jackson.autoconfigure.jsontest;
import java.util.Date; import java.util.Date;
import java.util.UUID; import java.util.UUID;
@ -22,15 +22,13 @@ import java.util.UUID;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.json.test.BasicJsonTester; import org.springframework.boot.jackson.autoconfigure.jsontest.app.ExampleBasicObject;
import org.springframework.boot.json.test.GsonTester; import org.springframework.boot.jackson.autoconfigure.jsontest.app.ExampleCustomObject;
import org.springframework.boot.json.test.JacksonTester; import org.springframework.boot.jackson.autoconfigure.jsontest.app.ExampleJsonApplication;
import org.springframework.boot.json.test.JsonContent; import org.springframework.boot.jackson.autoconfigure.jsontest.app.ExampleJsonObjectWithView;
import org.springframework.boot.json.test.JsonbTester; import org.springframework.boot.test.autoconfigure.json.JsonTest;
import org.springframework.boot.json.test.autoconfigure.app.ExampleBasicObject; import org.springframework.boot.test.json.JacksonTester;
import org.springframework.boot.json.test.autoconfigure.app.ExampleCustomObject; import org.springframework.boot.test.json.JsonContent;
import org.springframework.boot.json.test.autoconfigure.app.ExampleJsonApplication;
import org.springframework.boot.json.test.autoconfigure.app.ExampleJsonObjectWithView;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -46,9 +44,6 @@ import static org.assertj.core.api.Assertions.assertThat;
@ContextConfiguration(classes = ExampleJsonApplication.class) @ContextConfiguration(classes = ExampleJsonApplication.class)
class JsonTestIntegrationTests { class JsonTestIntegrationTests {
@Autowired
private BasicJsonTester basicJson;
@Autowired @Autowired
private JacksonTester<ExampleBasicObject> jacksonBasicJson; private JacksonTester<ExampleBasicObject> jacksonBasicJson;
@ -58,17 +53,6 @@ class JsonTestIntegrationTests {
@Autowired @Autowired
private JacksonTester<ExampleCustomObject> jacksonCustomJson; private JacksonTester<ExampleCustomObject> jacksonCustomJson;
@Autowired
private GsonTester<ExampleBasicObject> gsonJson;
@Autowired
private JsonbTester<ExampleBasicObject> jsonbJson;
@Test
void basicJson() {
assertThat(this.basicJson.from("{\"a\":\"b\"}")).hasJsonPathStringValue("@.a");
}
@Test @Test
void jacksonBasic() throws Exception { void jacksonBasic() throws Exception {
ExampleBasicObject object = new ExampleBasicObject(); ExampleBasicObject object = new ExampleBasicObject();
@ -82,20 +66,6 @@ class JsonTestIntegrationTests {
assertThat(this.jacksonCustomJson.write(object)).isEqualToJson("example.json"); assertThat(this.jacksonCustomJson.write(object)).isEqualToJson("example.json");
} }
@Test
void gson() throws Exception {
ExampleBasicObject object = new ExampleBasicObject();
object.setValue("spring");
assertThat(this.gsonJson.write(object)).isEqualToJson("example.json");
}
@Test
void jsonb() throws Exception {
ExampleBasicObject object = new ExampleBasicObject();
object.setValue("spring");
assertThat(this.jsonbJson.write(object)).isEqualToJson("example.json");
}
@Test @Test
void customView() throws Exception { void customView() throws Exception {
ExampleJsonObjectWithView object = new ExampleJsonObjectWithView(); ExampleJsonObjectWithView object = new ExampleJsonObjectWithView();

View File

@ -0,0 +1,50 @@
/*
* Copyright 2012-present 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.jackson.autoconfigure.jsontest;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.jackson.autoconfigure.jsontest.app.ExampleBasicObject;
import org.springframework.boot.jackson.autoconfigure.jsontest.app.ExampleJsonApplication;
import org.springframework.boot.test.autoconfigure.json.AutoConfigureJsonTesters;
import org.springframework.boot.test.autoconfigure.json.JsonTest;
import org.springframework.boot.test.json.JacksonTester;
import org.springframework.test.context.ContextConfiguration;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests for {@link JsonTest @JsonTest} with
* {@link AutoConfigureJsonTesters @AutoConfigureJsonTesters}.
*
* @author Phillip Webb
*/
@JsonTest
@AutoConfigureJsonTesters(enabled = false)
@ContextConfiguration(classes = ExampleJsonApplication.class)
class JsonTestWithAutoConfigureJsonTestersTests {
@Autowired(required = false)
private JacksonTester<ExampleBasicObject> jacksonTester;
@Test
void jackson() {
assertThat(this.jacksonTester).isNull();
}
}

View File

@ -0,0 +1,50 @@
/*
* Copyright 2012-present 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.jackson.autoconfigure.jsontest;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.jackson.autoconfigure.jsontest.app.ExampleBasicObject;
import org.springframework.boot.jackson.autoconfigure.jsontest.app.ExampleJsonApplication;
import org.springframework.boot.test.autoconfigure.json.AutoConfigureJsonTesters;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.json.JacksonTester;
import org.springframework.test.context.ContextConfiguration;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests for {@link SpringBootTest @SpringBootTest} with
* {@link AutoConfigureJsonTesters @AutoConfigureJsonTesters}.
*
* @author Andy Wilkinson
*/
@SpringBootTest
@AutoConfigureJsonTesters
@ContextConfiguration(classes = ExampleJsonApplication.class)
class SpringBootTestWithAutoConfigureJsonTestersTests {
@Autowired
private JacksonTester<ExampleBasicObject> jacksonTester;
@Test
void contextLoads() {
assertThat(this.jacksonTester).isNotNull();
}
}

View File

@ -0,0 +1,49 @@
/*
* Copyright 2012-present 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.jackson.autoconfigure.jsontest.app;
/**
* Example object to read/write as JSON.
*
* @author Phillip Webb
*/
public class ExampleBasicObject {
private String value;
public String getValue() {
return this.value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public boolean equals(Object obj) {
if (obj != null && obj.getClass() == getClass()) {
return this.value.equals(((ExampleBasicObject) obj).value);
}
return false;
}
@Override
public int hashCode() {
return this.value.hashCode();
}
}

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test.autoconfigure.app; package org.springframework.boot.jackson.autoconfigure.jsontest.app;
import java.util.Date; import java.util.Date;
import java.util.UUID; import java.util.UUID;

View File

@ -0,0 +1,31 @@
/*
* Copyright 2012-present 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.jackson.autoconfigure.jsontest.app;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.autoconfigure.json.JsonTest;
/**
* Example {@link SpringBootApplication @SpringBootApplication} for use with
* {@link JsonTest @JsonTest} tests.
*
* @author Phillip Webb
*/
@SpringBootApplication
public class ExampleJsonApplication {
}

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test.autoconfigure.app; package org.springframework.boot.jackson.autoconfigure.jsontest.app;
import java.util.Date; import java.util.Date;
import java.util.UUID; import java.util.UUID;
@ -28,7 +28,7 @@ import tools.jackson.databind.SerializationContext;
import org.springframework.boot.jackson.JsonComponent; import org.springframework.boot.jackson.JsonComponent;
import org.springframework.boot.jackson.ObjectValueDeserializer; import org.springframework.boot.jackson.ObjectValueDeserializer;
import org.springframework.boot.jackson.ObjectValueSerializer; import org.springframework.boot.jackson.ObjectValueSerializer;
import org.springframework.boot.json.test.autoconfigure.JsonTest; import org.springframework.boot.test.autoconfigure.json.JsonTest;
/** /**
* Example {@link JsonComponent @JsonComponent} for use with {@link JsonTest @JsonTest} * Example {@link JsonComponent @JsonComponent} for use with {@link JsonTest @JsonTest}

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.json.test.autoconfigure.app; package org.springframework.boot.jackson.autoconfigure.jsontest.app;
import com.fasterxml.jackson.annotation.JsonView; import com.fasterxml.jackson.annotation.JsonView;

View File

@ -1,43 +0,0 @@
/*
* Copyright 2012-present 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.
*/
plugins {
id "java-library"
id "org.springframework.boot.configuration-properties"
id "org.springframework.boot.deployed"
id "org.springframework.boot.optional-dependencies"
id "org.springframework.boot.test-slice"
}
description = "Spring Boot JSON Test"
dependencies {
api(project(":core:spring-boot-test-autoconfigure"))
optional(project(":core:spring-boot-autoconfigure"))
optional(project(":module:spring-boot-gson"))
optional(project(":module:spring-boot-jackson"))
optional(project(":module:spring-boot-jsonb"))
optional(project(":module:spring-boot-kotlin-serialization"))
optional("com.jayway.jsonpath:json-path")
optional("org.assertj:assertj-core")
optional("org.junit.jupiter:junit-jupiter-api")
optional("org.skyscreamer:jsonassert")
testImplementation(project(":test-support:spring-boot-test-support"))
testRuntimeOnly("ch.qos.logback:logback-classic")
}

View File

@ -1,261 +0,0 @@
/*
* Copyright 2012-present 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.json.test.autoconfigure;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import com.google.gson.Gson;
import jakarta.json.bind.Jsonb;
import org.jspecify.annotations.Nullable;
import tools.jackson.databind.json.JsonMapper;
import org.springframework.aot.hint.ExecutableMode;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.ReflectionHints;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.json.test.AbstractJsonMarshalTester;
import org.springframework.boot.json.test.BasicJsonTester;
import org.springframework.boot.json.test.GsonTester;
import org.springframework.boot.json.test.JacksonTester;
import org.springframework.boot.json.test.JsonbTester;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportRuntimeHints;
import org.springframework.context.annotation.Scope;
import org.springframework.core.ResolvableType;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
/**
* Auto-configuration for Json testers.
*
* @author Phillip Webb
* @author Eddú Meléndez
* @since 4.0.0
* @see AutoConfigureJsonTesters
*/
@AutoConfiguration(afterName = { "org.springframework.boot.jackson.autoconfigure.JacksonAutoConfiguration",
"org.springframework.boot.jsonb.autoconfigure.JsonbAutoConfiguration",
"org.springframework.boot.gson.autoconfigure.GsonAutoConfiguration" })
@ConditionalOnClass(name = "org.assertj.core.api.Assert")
@ConditionalOnBooleanProperty("spring.test.jsontesters.enabled")
public final class JsonTestersAutoConfiguration {
@Bean
static JsonMarshalTestersBeanPostProcessor jsonMarshalTestersBeanPostProcessor() {
return new JsonMarshalTestersBeanPostProcessor();
}
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@ImportRuntimeHints(BasicJsonTesterRuntimeHints.class)
FactoryBean<BasicJsonTester> basicJsonTesterFactoryBean() {
return new JsonTesterFactoryBean<BasicJsonTester, Void>(BasicJsonTester.class, null);
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(JsonMapper.class)
static class JacksonJsonTestersConfiguration {
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@ConditionalOnBean(JsonMapper.class)
@ImportRuntimeHints(JacksonTesterRuntimeHints.class)
FactoryBean<JacksonTester<?>> jacksonTesterFactoryBean(JsonMapper mapper) {
return new JsonTesterFactoryBean<>(JacksonTester.class, mapper);
}
static class JacksonTesterRuntimeHints extends AbstractJsonMarshalTesterRuntimeHints {
JacksonTesterRuntimeHints() {
super(JacksonTester.class);
}
}
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Gson.class)
static class GsonJsonTestersConfiguration {
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@ConditionalOnBean(Gson.class)
@ImportRuntimeHints(GsonTesterRuntimeHints.class)
FactoryBean<GsonTester<?>> gsonTesterFactoryBean(Gson gson) {
return new JsonTesterFactoryBean<>(GsonTester.class, gson);
}
static class GsonTesterRuntimeHints extends AbstractJsonMarshalTesterRuntimeHints {
GsonTesterRuntimeHints() {
super(GsonTester.class);
}
}
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Jsonb.class)
static class JsonbJsonTesterConfiguration {
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@ConditionalOnBean(Jsonb.class)
@ImportRuntimeHints(JsonbJsonTesterRuntimeHints.class)
FactoryBean<JsonbTester<?>> jsonbTesterFactoryBean(Jsonb jsonb) {
return new JsonTesterFactoryBean<>(JsonbTester.class, jsonb);
}
static class JsonbJsonTesterRuntimeHints extends AbstractJsonMarshalTesterRuntimeHints {
JsonbJsonTesterRuntimeHints() {
super(JsonbTester.class);
}
}
}
/**
* {@link FactoryBean} used to create JSON Tester instances.
*
* @param <T> the object type
* @param <M> the marshaller type
*/
static class JsonTesterFactoryBean<T, M> implements FactoryBean<T> {
private final Class<?> objectType;
private final @Nullable M marshaller;
JsonTesterFactoryBean(Class<?> objectType, @Nullable M marshaller) {
this.objectType = objectType;
this.marshaller = marshaller;
}
@Override
public boolean isSingleton() {
return false;
}
@Override
@SuppressWarnings("unchecked")
public T getObject() throws Exception {
if (this.marshaller == null) {
Constructor<?> constructor = this.objectType.getDeclaredConstructor();
ReflectionUtils.makeAccessible(constructor);
return (T) BeanUtils.instantiateClass(constructor);
}
Constructor<?>[] constructors = this.objectType.getDeclaredConstructors();
for (Constructor<?> constructor : constructors) {
if (constructor.getParameterCount() == 1
&& constructor.getParameterTypes()[0].isInstance(this.marshaller)) {
ReflectionUtils.makeAccessible(constructor);
return (T) BeanUtils.instantiateClass(constructor, this.marshaller);
}
}
throw new IllegalStateException(this.objectType + " does not have a usable constructor");
}
@Override
public Class<?> getObjectType() {
return this.objectType;
}
}
/**
* {@link BeanPostProcessor} used to initialize JSON testers.
*/
static class JsonMarshalTestersBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
ReflectionUtils.doWithFields(bean.getClass(), (field) -> processField(bean, field));
return bean;
}
private void processField(Object bean, Field field) {
if (AbstractJsonMarshalTester.class.isAssignableFrom(field.getType())) {
initializeTester(bean, field, bean.getClass(), ResolvableType.forField(field).getGeneric());
}
else if (BasicJsonTester.class.isAssignableFrom(field.getType())) {
initializeTester(bean, field, bean.getClass());
}
}
private void initializeTester(Object bean, Field field, Object... args) {
ReflectionUtils.makeAccessible(field);
Object tester = ReflectionUtils.getField(field, bean);
if (tester != null) {
ReflectionTestUtils.invokeMethod(tester, "initialize", args);
}
}
}
@SuppressWarnings("rawtypes")
static class AbstractJsonMarshalTesterRuntimeHints implements RuntimeHintsRegistrar {
private final Class<? extends AbstractJsonMarshalTester> tester;
AbstractJsonMarshalTesterRuntimeHints(Class<? extends AbstractJsonMarshalTester> tester) {
this.tester = tester;
}
@Override
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
ReflectionHints reflection = hints.reflection();
reflection.registerType(this.tester, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
Method method = ReflectionUtils.findMethod(this.tester, "initialize", Class.class, ResolvableType.class);
Assert.state(method != null, "'method' must not be null");
reflection.registerMethod(method, ExecutableMode.INVOKE);
}
}
static class BasicJsonTesterRuntimeHints implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
ReflectionHints reflection = hints.reflection();
reflection.registerType(BasicJsonTester.class, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
Method method = ReflectionUtils.findMethod(BasicJsonTester.class, "initialize", Class.class);
Assert.state(method != null, "'method' must not be null");
reflection.registerMethod(method, ExecutableMode.INVOKE);
}
}
}

View File

@ -1,10 +0,0 @@
{
"properties": [
{
"name": "spring.test.jsontesters.enabled",
"type": "java.lang.Boolean",
"description": "Whether auto-configuration of JSON testers is enabled.",
"defaultValue": "true"
}
]
}

View File

@ -1,3 +0,0 @@
# Spring Test Context Customizer Factories
org.springframework.test.context.ContextCustomizerFactory=\
org.springframework.boot.json.test.DuplicateJsonObjectContextCustomizerFactory

View File

@ -1,4 +0,0 @@
optional:org.springframework.boot.gson.autoconfigure.GsonAutoConfiguration
optional:org.springframework.boot.jackson.autoconfigure.JacksonAutoConfiguration
optional:org.springframework.boot.jsonb.autoconfigure.JsonbAutoConfiguration
optional:org.springframework.boot.kotlin.serialization.autoconfigure.KotlinSerializationAutoConfiguration

View File

@ -1 +0,0 @@
org.springframework.boot.json.test.autoconfigure.JsonTestersAutoConfiguration

Some files were not shown because too many files have changed in this diff Show More