Support for @Arguments method parameter
Closes gh-258
This commit is contained in:
@@ -1009,9 +1009,13 @@ Schema mapping handler methods can have any of the following method arguments:
|
||||
| Method Argument | Description
|
||||
|
||||
| `@Argument`
|
||||
| For access to field arguments with conversion.
|
||||
| For access to a named field argument converted to a higher-level, typed Object.
|
||||
See <<controllers-schema-mapping-argument>>.
|
||||
|
||||
| `@Arguments`
|
||||
| For access to all field arguments converted to a higher-level, typed Object.
|
||||
See <<controllers-schema-mapping-arguments>>.
|
||||
|
||||
| `@ProjectedPayload` Interface
|
||||
| For access to field arguments through a project interface.
|
||||
See <<controllers-schema-mapping-projectedpayload-argument>>.
|
||||
@@ -1056,12 +1060,15 @@ Schema mapping handler methods can return any value, including Reactor `Mono` an
|
||||
[[controllers-schema-mapping-argument]]
|
||||
==== `@Argument`
|
||||
|
||||
In GraphQL Java, the `DataFetchingEnvironment` provides access to field-specific argument
|
||||
values. The arguments are available as simple scalar values such as String, or as a `Map`
|
||||
of values for more complex input, or a `List` of values.
|
||||
In GraphQL Java, `DataFetchingEnvironment` provides access to a map of field-specific
|
||||
argument values. The values can be simple scalar values (e.g. String, Long), a `Map` of
|
||||
values for more complex input, or a `List` of values.
|
||||
|
||||
Use `@Argument` to access an argument for the field that maps to the handler method. You
|
||||
can declare such a method parameter to be of any type.
|
||||
Use the `@Argument` annotation to inject a named field argument into a handler method.
|
||||
The method parameter can be a higher-level, typed Object of any type. It is created and
|
||||
initialized from the named field argument value(s), either matching them to single data
|
||||
constructor parameters, or using the default constructor and then matching keys onto
|
||||
Object properties through a `org.springframework.validation.DataBinder`:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1080,20 +1087,32 @@ can declare such a method parameter to be of any type.
|
||||
}
|
||||
----
|
||||
|
||||
You can explicitly specify the argument name, for example `@Argument("bookInput")`, or if
|
||||
it not specified, it defaults to the method parameter name, but this requires the
|
||||
`-parameters` compiler flag with Java 8+ or debugging information from the compiler.
|
||||
By default, if the method parameter name is available (requires the `-parameters` compiler
|
||||
flag with Java 8+ or debugging info from the compiler), it is used to look up the argument.
|
||||
If needed, you can customize the name through the annotation, e.g. `@Argument("bookInput")`.
|
||||
|
||||
The `@Argument` annotation does not have a "required" flag, nor the option to specify a
|
||||
default value. Both of these can be specified at the GraphQL schema level and are enforced
|
||||
by the GraphQL Engine.
|
||||
TIP: The `@Argument` annotation does not have a "required" flag, nor the option to
|
||||
specify a default value. Both of these can be specified at the GraphQL schema level and
|
||||
are enforced by the GraphQL Engine.
|
||||
|
||||
You can use `@Argument` on a `Map<String, Object>` argument, to obtain all argument
|
||||
values. The name attribute on `@Argument` must not be set.
|
||||
|
||||
|
||||
[[controllers-schema-mapping-arguments]]
|
||||
==== `@Arguments`
|
||||
|
||||
Use the `@Arguments` annotation, if you want to bind the full arguments map onto a single
|
||||
target Object, in contrast to `@Argument`, which binds a specific, named argument.
|
||||
|
||||
For example, `@Argument BookInput bookInput` uses the value of the argument "bookInput"
|
||||
to initialize `BookInput`, while `@Arguments` uses the full arguments map and in that
|
||||
case, top-level arguments are bound to `BookInput` properties.
|
||||
|
||||
|
||||
|
||||
[[controllers-schema-mapping-validation]]
|
||||
==== `@Argument` validation
|
||||
==== `@Argument(s)` Validation
|
||||
|
||||
If a {spring-framework-ref-docs}/core.html#validation-beanvalidation-overview[Bean Validation]
|
||||
`Validator` (or typically, a `LocalValidatorFactoryBean`) bean is present in the application context,
|
||||
@@ -1138,6 +1157,7 @@ Unlike Spring MVC, handler method signatures do not support the injection of `Bi
|
||||
for reacting to validation errors: those are globally dealt with as exceptions.
|
||||
====
|
||||
|
||||
|
||||
[[controllers-schema-mapping-projectedpayload-argument]]
|
||||
==== `@ProjectPayload` Interface
|
||||
|
||||
|
||||
@@ -31,12 +31,19 @@ import org.springframework.core.annotation.AliasFor;
|
||||
* and a parameter name is not specified, then the map parameter is populated
|
||||
* via {@link graphql.schema.DataFetchingEnvironment#getArguments()}.
|
||||
*
|
||||
* <p>The target method parameter can be a higher-level, typed Object of any
|
||||
* type. It is created and initialized from the named field argument value(s),
|
||||
* either matching them to single data constructor parameters, or using the
|
||||
* default constructor and then matching keys onto Object properties through
|
||||
* a {@link org.springframework.validation.DataBinder}.
|
||||
*
|
||||
* <p>Note that this annotation has neither a "required" flag nor the option to
|
||||
* specify a default value, both of which can be specified at the GraphQL schema
|
||||
* level and are enforced by the GraphQL Java engine.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 1.0.0
|
||||
* @see Arguments
|
||||
*/
|
||||
@Target(ElementType.PARAMETER)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2002-2022 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.graphql.data.method.annotation;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Similar to {@link Argument @Argument} but using the full map of argument
|
||||
* values as the source of values to bind to the target Object.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 1.0.0
|
||||
* @see Argument
|
||||
*/
|
||||
@Target(ElementType.PARAMETER)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface Arguments {
|
||||
|
||||
}
|
||||
@@ -161,6 +161,7 @@ public class AnnotatedControllerConfigurer
|
||||
this.argumentResolvers.addResolver(new ArgumentMapMethodArgumentResolver());
|
||||
GraphQlArgumentInitializer initializer = new GraphQlArgumentInitializer(this.conversionService);
|
||||
this.argumentResolvers.addResolver(new ArgumentMethodArgumentResolver(initializer));
|
||||
this.argumentResolvers.addResolver(new ArgumentsMethodArgumentResolver(initializer));
|
||||
this.argumentResolvers.addResolver(new ContextValueMethodArgumentResolver());
|
||||
|
||||
// Type based
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2002-2022 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.graphql.data.method.annotation.support;
|
||||
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.graphql.data.GraphQlArgumentInitializer;
|
||||
import org.springframework.graphql.data.method.HandlerMethodArgumentResolver;
|
||||
import org.springframework.graphql.data.method.annotation.Arguments;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Resolver for {@link Arguments @Arguments} annotated method parameters,
|
||||
* obtained via {@link DataFetchingEnvironment#getArgument(String)} and
|
||||
* converted to the declared type of the method parameter.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class ArgumentsMethodArgumentResolver implements HandlerMethodArgumentResolver {
|
||||
|
||||
private final GraphQlArgumentInitializer argumentInitializer;
|
||||
|
||||
|
||||
public ArgumentsMethodArgumentResolver(GraphQlArgumentInitializer initializer) {
|
||||
Assert.notNull(initializer, "GraphQlArgumentInitializer is required");
|
||||
this.argumentInitializer = initializer;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
return parameter.getParameterAnnotation(Arguments.class) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveArgument(MethodParameter parameter, DataFetchingEnvironment environment) throws Exception {
|
||||
ResolvableType resolvableType = ResolvableType.forMethodParameter(parameter);
|
||||
return this.argumentInitializer.initializeArgument(environment, null, resolvableType);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2021 the original author or authors.
|
||||
* Copyright 2020-2022 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.
|
||||
@@ -17,20 +17,11 @@
|
||||
package org.springframework.graphql.data.method.annotation.support;
|
||||
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import graphql.schema.DataFetchingEnvironmentImpl;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.core.DefaultParameterNameDiscoverer;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.annotation.SynthesizingMethodParameter;
|
||||
import org.springframework.format.support.DefaultFormattingConversionService;
|
||||
import org.springframework.graphql.Book;
|
||||
import org.springframework.graphql.data.GraphQlArgumentInitializer;
|
||||
@@ -39,7 +30,6 @@ import org.springframework.graphql.data.method.annotation.Argument;
|
||||
import org.springframework.graphql.data.method.annotation.MutationMapping;
|
||||
import org.springframework.graphql.data.method.annotation.QueryMapping;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -47,85 +37,69 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* Tests for {@link ArgumentMethodArgumentResolver}.
|
||||
* @author Brian Clozel
|
||||
*/
|
||||
class ArgumentMethodArgumentResolverTests {
|
||||
class ArgumentMethodArgumentResolverTests extends ArgumentResolverTestSupport {
|
||||
|
||||
private final ObjectMapper mapper = new ObjectMapper();
|
||||
private final HandlerMethodArgumentResolver resolver = new ArgumentMethodArgumentResolver(
|
||||
new GraphQlArgumentInitializer(new DefaultFormattingConversionService()));
|
||||
|
||||
private final HandlerMethodArgumentResolver resolver =
|
||||
new ArgumentMethodArgumentResolver(new GraphQlArgumentInitializer(new DefaultFormattingConversionService()));
|
||||
|
||||
@Test
|
||||
void shouldSupportAnnotatedParameters() {
|
||||
Method bookById = ClassUtils.getMethod(BookController.class, "bookById", Long.class);
|
||||
MethodParameter methodParameter = methodParam(bookById, 0);
|
||||
|
||||
assertThat(resolver.supportsParameter(methodParameter)).isTrue();
|
||||
MethodParameter methodParameter = methodParam(BookController.class, "bookById", Long.class);
|
||||
assertThat(this.resolver.supportsParameter(methodParameter)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotSupportParametersWithoutAnnotation() {
|
||||
Method notSupported = ClassUtils.getMethod(BookController.class, "notSupported", String.class);
|
||||
MethodParameter methodParameter = methodParam(notSupported, 0);
|
||||
|
||||
assertThat(resolver.supportsParameter(methodParameter)).isFalse();
|
||||
MethodParameter methodParameter = methodParam(BookController.class, "notSupported", String.class);
|
||||
assertThat(this.resolver.supportsParameter(methodParameter)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldResolveBasicTypeArgument() throws Exception {
|
||||
Method bookById = ClassUtils.getMethod(BookController.class, "bookById", Long.class);
|
||||
DataFetchingEnvironment environment = initEnvironment("{\"id\": 42 }");
|
||||
Object result = resolver.resolveArgument(methodParam(bookById, 0), environment);
|
||||
Object result = this.resolver.resolveArgument(
|
||||
methodParam(BookController.class, "bookById", Long.class),
|
||||
environment("{\"id\": 42 }"));
|
||||
|
||||
assertThat(result).isNotNull().isInstanceOf(Long.class).isEqualTo(42L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldResolveJavaBeanArgument() throws Exception {
|
||||
Method addBook = ClassUtils.getMethod(BookController.class, "addBook", BookInput.class);
|
||||
String payload = "{\"bookInput\": { \"name\": \"test name\", \"authorId\": 42} }";
|
||||
DataFetchingEnvironment environment = initEnvironment(payload);
|
||||
Object result = resolver.resolveArgument(methodParam(addBook, 0), environment);
|
||||
Object result = this.resolver.resolveArgument(
|
||||
methodParam(BookController.class, "addBook", BookInput.class),
|
||||
environment("{\"bookInput\": { \"name\": \"test name\", \"authorId\": 42} }"));
|
||||
|
||||
assertThat(result).isNotNull().isInstanceOf(BookInput.class);
|
||||
assertThat((BookInput) result).hasFieldOrPropertyWithValue("name", "test name")
|
||||
assertThat(result).isNotNull().isInstanceOf(BookInput.class)
|
||||
.hasFieldOrPropertyWithValue("name", "test name")
|
||||
.hasFieldOrPropertyWithValue("authorId", 42L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldResolveListOfJavaBeansArgument() throws Exception {
|
||||
Method addBooks = ClassUtils.getMethod(BookController.class, "addBooks", List.class);
|
||||
String payload = "{\"books\": [{ \"name\": \"first\", \"authorId\": 42}, { \"name\": \"second\", \"authorId\": 24}] }";
|
||||
DataFetchingEnvironment environment = initEnvironment(payload);
|
||||
Object result = resolver.resolveArgument(methodParam(addBooks, 0), environment);
|
||||
Object result = this.resolver.resolveArgument(
|
||||
methodParam(BookController.class, "addBooks", List.class),
|
||||
environment("{\"books\": [" +
|
||||
"{ \"name\": \"first\", \"authorId\": 42}, " +
|
||||
"{ \"name\": \"second\", \"authorId\": 24}] }"));
|
||||
|
||||
assertThat(result).isNotNull().isInstanceOf(List.class);
|
||||
assertThat(result).asList().allMatch(item -> item instanceof Book)
|
||||
assertThat(result).isNotNull()
|
||||
.isInstanceOf(List.class).asList()
|
||||
.allMatch(item -> item instanceof Book)
|
||||
.extracting("name").containsExactly("first", "second");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldResolveArgumentWithConversionService() throws Exception {
|
||||
Method bookByKeyword = ClassUtils.getMethod(BookController.class, "bookByKeyword", Keyword.class);
|
||||
String payload = "{\"keyword\": \"test\" }";
|
||||
DataFetchingEnvironment environment = initEnvironment(payload);
|
||||
Object result = resolver.resolveArgument(methodParam(bookByKeyword, 0), environment);
|
||||
Object result = this.resolver.resolveArgument(
|
||||
methodParam(BookController.class, "bookByKeyword", Keyword.class),
|
||||
environment("{\"keyword\": \"test\" }"));
|
||||
|
||||
assertThat(result).isNotNull().isInstanceOf(Keyword.class);
|
||||
assertThat((Keyword) result).hasFieldOrPropertyWithValue("term", "test");
|
||||
}
|
||||
|
||||
private MethodParameter methodParam(Method method, int index) {
|
||||
MethodParameter methodParameter = new SynthesizingMethodParameter(method, index);
|
||||
methodParameter.initParameterNameDiscovery(new DefaultParameterNameDiscoverer());
|
||||
return methodParameter;
|
||||
}
|
||||
|
||||
private DataFetchingEnvironment initEnvironment(String jsonPayload) throws JsonProcessingException {
|
||||
Map<String, Object> arguments = mapper.readValue(jsonPayload, new TypeReference<Map<String, Object>>() {});
|
||||
return DataFetchingEnvironmentImpl.newDataFetchingEnvironment().arguments(arguments).build();
|
||||
assertThat(result).isNotNull().isInstanceOf(Keyword.class).hasFieldOrPropertyWithValue("term", "test");
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings({"ConstantConditions", "unused"})
|
||||
@Controller
|
||||
static class BookController {
|
||||
|
||||
@@ -155,6 +129,7 @@ class ArgumentMethodArgumentResolverTests {
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings({"NotNullFieldNotInitialized", "unused"})
|
||||
static class BookInput {
|
||||
|
||||
String name;
|
||||
@@ -178,6 +153,8 @@ class ArgumentMethodArgumentResolverTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
static class Keyword {
|
||||
|
||||
String term;
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2020-2022 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.graphql.data.method.annotation.support;
|
||||
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import graphql.schema.DataFetchingEnvironmentImpl;
|
||||
|
||||
import org.springframework.core.DefaultParameterNameDiscoverer;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.annotation.SynthesizingMethodParameter;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Base class to test resolving {@link @Argument} and {@link @Arguments}
|
||||
* annotated method parameters.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
class ArgumentResolverTestSupport {
|
||||
|
||||
private static final TypeReference<Map<String, Object>> MAP_TYPE_REFERENCE =
|
||||
new TypeReference<Map<String, Object>>() {};
|
||||
|
||||
|
||||
private final ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
|
||||
protected MethodParameter methodParam(Class<?> controller, String methodName, Class<?>... parameters) {
|
||||
Method method = ClassUtils.getMethod(controller, methodName, parameters);
|
||||
MethodParameter methodParam = new SynthesizingMethodParameter(method, 0);
|
||||
methodParam.initParameterNameDiscovery(new DefaultParameterNameDiscoverer());
|
||||
return methodParam;
|
||||
}
|
||||
|
||||
protected DataFetchingEnvironment environment(String argumentsJson) throws JsonProcessingException {
|
||||
Map<String, Object> arguments = this.mapper.readValue(argumentsJson, MAP_TYPE_REFERENCE);
|
||||
return DataFetchingEnvironmentImpl.newDataFetchingEnvironment().arguments(arguments).build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright 2020-2022 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.graphql.data.method.annotation.support;
|
||||
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.format.support.DefaultFormattingConversionService;
|
||||
import org.springframework.graphql.Book;
|
||||
import org.springframework.graphql.data.GraphQlArgumentInitializer;
|
||||
import org.springframework.graphql.data.method.HandlerMethodArgumentResolver;
|
||||
import org.springframework.graphql.data.method.annotation.Arguments;
|
||||
import org.springframework.graphql.data.method.annotation.MutationMapping;
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link ArgumentsMethodArgumentResolver}.
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
class ArgumentsMethodArgumentResolverTests extends ArgumentResolverTestSupport {
|
||||
|
||||
private final HandlerMethodArgumentResolver resolver = new ArgumentsMethodArgumentResolver(
|
||||
new GraphQlArgumentInitializer(new DefaultFormattingConversionService()));
|
||||
|
||||
|
||||
@Test
|
||||
void shouldSupportAnnotatedParameters() {
|
||||
MethodParameter methodParameter = methodParam(BookController.class, "addBook", BookInput.class);
|
||||
assertThat(resolver.supportsParameter(methodParameter)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotSupportParametersWithoutAnnotation() {
|
||||
MethodParameter methodParameter = methodParam(BookController.class, "notSupported", String.class);
|
||||
assertThat(resolver.supportsParameter(methodParameter)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldResolveJavaBeanArgument() throws Exception {
|
||||
Object result = resolver.resolveArgument(
|
||||
methodParam(BookController.class, "addBook", BookInput.class),
|
||||
environment("{\"name\":\"test name\", \"authorId\":42}"));
|
||||
|
||||
assertThat(result).isNotNull().isInstanceOf(BookInput.class)
|
||||
.hasFieldOrPropertyWithValue("name", "test name")
|
||||
.hasFieldOrPropertyWithValue("authorId", 42L);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings({"ConstantConditions", "unused"})
|
||||
@Controller
|
||||
static class BookController {
|
||||
|
||||
public void notSupported(String param) {
|
||||
}
|
||||
|
||||
@MutationMapping
|
||||
public Book addBook(@Arguments BookInput bookInput) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings({"NotNullFieldNotInitialized", "unused"})
|
||||
static class BookInput {
|
||||
|
||||
String name;
|
||||
|
||||
Long authorId;
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Long getAuthorId() {
|
||||
return this.authorId;
|
||||
}
|
||||
|
||||
public void setAuthorId(Long authorId) {
|
||||
this.authorId = authorId;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user