Skip to content

Commit 59912bc

Browse files
committed
added junit advice tests
1 parent 68729d6 commit 59912bc

File tree

13 files changed

+645
-95
lines changed

13 files changed

+645
-95
lines changed

grpc-server-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/server/advice/GrpcAdviceDiscoverer.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ public class GrpcAdviceDiscoverer implements InitializingBean, ApplicationContex
5454
public void afterPropertiesSet() throws Exception {
5555

5656
annotatedBeans = applicationContext.getBeansWithAnnotation(GrpcAdvice.class);
57+
annotatedBeans.forEach(
58+
(key, value) -> log.debug("Found gRPC advice: " + key + ", class: " + value.getClass().getName()));
59+
5760
annotatedClasses = extractClassType();
5861
annotatedMethods = findAnnotatedMethods();
5962
}
@@ -83,12 +86,12 @@ boolean isAnnotationPresent() {
8386
return !annotatedClasses.isEmpty() && !annotatedMethods.isEmpty();
8487
}
8588

86-
Map<String, Object> getAnnotatedBeans() {
89+
public Map<String, Object> getAnnotatedBeans() {
8790
Assert.state(annotatedBeans != null, "@GrpcAdvice annotation scanning failed.");
8891
return annotatedBeans;
8992
}
9093

91-
Set<Method> getAnnotatedMethods() {
94+
public Set<Method> getAnnotatedMethods() {
9295
Assert.state(annotatedMethods != null, "@GrpcExceptionHandler annotation scanning failed.");
9396
return annotatedMethods;
9497
}

grpc-server-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/server/advice/GrpcAdviceExceptionListener.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ private Status resolveStatus(Object mappedReturnType) {
8282
return Status.fromThrowable((Throwable) mappedReturnType);
8383
}
8484
throw new IllegalStateException(String.format(
85-
"Error for mapped return type [%s] inside @GrpcServiceAdvice, it has to be of type: "
85+
"Error for mapped return type [%s] inside @GrpcAdvice, it has to be of type: "
8686
+ "[Status, StatusException, StatusRuntimeException, Throwable] ",
8787
mappedReturnType));
8888
}
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,14 @@
2525
import org.springframework.core.type.AnnotatedTypeMetadata;
2626

2727
/**
28-
* Condition to check if {@link GrpcAdvice @GrpcServiceAdvice} is present. Mainly checking if
29-
* {@link GrpcAdviceDiscoverer} should be a instantiated.<br>
28+
* Condition to check if {@link GrpcAdvice @GrpcAdvice} is present. Mainly checking if {@link GrpcAdviceDiscoverer}
29+
* should be a instantiated.<br>
3030
* <br>
3131
*
3232
* @author Andjelko Perisic ([email protected])
3333
* @see GrpcAdviceDiscoverer
3434
*/
35-
public class GrpcServiceAdviceIsPresent implements ConfigurationCondition {
35+
public class GrpcAdviceIsPresent implements ConfigurationCondition {
3636

3737
@Override
3838
public ConfigurationPhase getConfigurationPhase() {

grpc-server-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/server/advice/GrpcExceptionHandlerMethodResolver.java

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -87,21 +87,28 @@ private Set<Class<? extends Throwable>> extractExceptions(Class<?>[] methodParam
8787

8888
Set<Class<? extends Throwable>> exceptionsToBeMapped = new HashSet<>();
8989
for (Class<? extends Throwable> annoClass : annotatedExceptions) {
90-
boolean annoTypeIsNotSuperclass = Arrays.stream(methodParamTypes).noneMatch(annoClass::isAssignableFrom);
91-
if (annoTypeIsNotSuperclass) {
92-
throw new IllegalStateException(
93-
String.format(
94-
"@GrpcExceptionHandler annotated method declared exception [%s] "
95-
+ "is NOT superclass of listed parameter arguments [%s]",
96-
annoClass, Arrays.toString(methodParamTypes)));
97-
}
90+
if (methodParamTypes.length > 0)
91+
validateAppropriateParentException(annoClass, methodParamTypes);
9892
exceptionsToBeMapped.add(annoClass);
9993
}
10094

10195
addMappingInCaseAnnotationIsEmpty(methodParamTypes, exceptionsToBeMapped);
10296
return exceptionsToBeMapped;
10397
}
10498

99+
private void validateAppropriateParentException(Class<? extends Throwable> annoClass, Class<?>[] methodParamTypes) {
100+
101+
boolean paramTypeIsNotSuperclass =
102+
Arrays.stream(methodParamTypes).noneMatch(param -> param.isAssignableFrom(annoClass));
103+
if (paramTypeIsNotSuperclass) {
104+
throw new IllegalStateException(
105+
String.format(
106+
"no listed parameter argument [%s] is equal or superclass "
107+
+ "of annotated @GrpcExceptionHandler method declared exception [%s].",
108+
Arrays.toString(methodParamTypes), annoClass));
109+
}
110+
}
111+
105112
private void addMappingInCaseAnnotationIsEmpty(
106113
Class<?>[] methodParamTypes,
107114
Set<Class<? extends Throwable>> exceptionsToBeMapped) {

grpc-server-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/server/autoconfigure/GrpcAdviceAutoConfiguration.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
package net.devh.boot.grpc.server.autoconfigure;
1919

20-
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
20+
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
2121
import org.springframework.boot.context.properties.EnableConfigurationProperties;
2222
import org.springframework.context.annotation.Bean;
2323
import org.springframework.context.annotation.Conditional;
@@ -29,9 +29,9 @@
2929
import net.devh.boot.grpc.server.advice.GrpcAdviceDiscoverer;
3030
import net.devh.boot.grpc.server.advice.GrpcAdviceExceptionHandler;
3131
import net.devh.boot.grpc.server.advice.GrpcAdviceExceptionInterceptor;
32+
import net.devh.boot.grpc.server.advice.GrpcAdviceIsPresent;
3233
import net.devh.boot.grpc.server.advice.GrpcExceptionHandler;
3334
import net.devh.boot.grpc.server.advice.GrpcExceptionHandlerMethodResolver;
34-
import net.devh.boot.grpc.server.advice.GrpcServiceAdviceIsPresent;
3535
import net.devh.boot.grpc.server.interceptor.GrpcGlobalServerInterceptor;
3636

3737
/**
@@ -47,12 +47,12 @@
4747
*/
4848
@Configuration(proxyBeanMethods = false)
4949
@EnableConfigurationProperties
50-
@Conditional(GrpcServiceAdviceIsPresent.class)
51-
@AutoConfigureAfter(GrpcServerAutoConfiguration.class)
50+
@Conditional(GrpcAdviceIsPresent.class)
51+
@AutoConfigureBefore(GrpcServerFactoryAutoConfiguration.class)
5252
public class GrpcAdviceAutoConfiguration {
5353

5454
@Bean
55-
public GrpcAdviceDiscoverer grpcServiceAdviceDiscoverer() {
55+
public GrpcAdviceDiscoverer grpcAdviceDiscoverer() {
5656
return new GrpcAdviceDiscoverer();
5757
}
5858

@@ -63,14 +63,14 @@ public GrpcExceptionHandlerMethodResolver grpcExceptionHandlerMethodResolver(
6363
}
6464

6565
@Bean
66-
public GrpcAdviceExceptionHandler grpcServiceAdviceExceptionHandler(
66+
public GrpcAdviceExceptionHandler grpcAdviceExceptionHandler(
6767
GrpcExceptionHandlerMethodResolver grpcExceptionHandlerMethodResolver) {
6868
return new GrpcAdviceExceptionHandler(grpcExceptionHandlerMethodResolver);
6969
}
7070

7171
@GrpcGlobalServerInterceptor
7272
@Order(InterceptorOrder.ORDER_GLOBAL_EXCEPTION_HANDLING)
73-
public GrpcAdviceExceptionInterceptor grpcServiceAdviceExceptionInterceptor(
73+
public GrpcAdviceExceptionInterceptor grpcAdviceExceptionInterceptor(
7474
GrpcAdviceExceptionHandler grpcAdviceExceptionHandler) {
7575
return new GrpcAdviceExceptionInterceptor(grpcAdviceExceptionHandler);
7676
}

grpc-server-spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ net.devh.boot.grpc.server.autoconfigure.GrpcServerAutoConfiguration,\
77
net.devh.boot.grpc.server.autoconfigure.GrpcServerFactoryAutoConfiguration,\
88
net.devh.boot.grpc.server.autoconfigure.GrpcServerSecurityAutoConfiguration,\
99
net.devh.boot.grpc.server.autoconfigure.GrpcServerMetricAutoConfiguration,\
10-
net.devh.boot.grpc.server.autoconfigure.GrpcServerTraceAutoConfiguration
10+
net.devh.boot.grpc.server.autoconfigure.GrpcServerTraceAutoConfiguration,\
11+
net.devh.boot.grpc.server.autoconfigure.GrpcAdviceAutoConfiguration
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
/*
2+
* Copyright (c) 2016-2020 Michael Zhang <[email protected]>
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
5+
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
6+
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
7+
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
8+
*
9+
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
10+
* Software.
11+
*
12+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
13+
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
14+
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
15+
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
16+
*/
17+
18+
package net.devh.boot.grpc.test.advice;
19+
20+
import static net.devh.boot.grpc.test.util.FutureAssertions.assertFutureThrows;
21+
import static org.assertj.core.api.Assertions.assertThat;
22+
import static org.junit.jupiter.api.Assertions.assertNotNull;
23+
import static org.junit.jupiter.api.Assertions.assertThrows;
24+
25+
import java.util.concurrent.TimeUnit;
26+
27+
import javax.annotation.PostConstruct;
28+
29+
import com.google.protobuf.Empty;
30+
31+
import io.grpc.Channel;
32+
import io.grpc.Metadata;
33+
import io.grpc.Status;
34+
import io.grpc.StatusRuntimeException;
35+
import io.grpc.internal.testing.StreamRecorder;
36+
import lombok.extern.slf4j.Slf4j;
37+
import net.devh.boot.grpc.client.inject.GrpcClient;
38+
import net.devh.boot.grpc.test.proto.SomeType;
39+
import net.devh.boot.grpc.test.proto.TestServiceGrpc;
40+
import net.devh.boot.grpc.test.proto.TestServiceGrpc.TestServiceBlockingStub;
41+
import net.devh.boot.grpc.test.proto.TestServiceGrpc.TestServiceFutureStub;
42+
import net.devh.boot.grpc.test.proto.TestServiceGrpc.TestServiceStub;
43+
44+
/**
45+
* A test checking that the server and client can start and connect to each other with proper exception handling.
46+
*
47+
* @author Andjelko Perisic ([email protected])
48+
*/
49+
@Slf4j
50+
abstract class AbstractSimpleServerClientTest {
51+
52+
@GrpcClient("test")
53+
protected Channel channel;
54+
@GrpcClient("test")
55+
protected TestServiceStub testServiceStub;
56+
@GrpcClient("test")
57+
protected TestServiceBlockingStub testServiceBlockingStub;
58+
@GrpcClient("test")
59+
protected TestServiceFutureStub testServiceFutureStub;
60+
61+
@PostConstruct
62+
protected void init() {
63+
// Test injection
64+
assertNotNull(this.channel, "channel");
65+
assertNotNull(this.testServiceBlockingStub, "testServiceBlockingStub");
66+
assertNotNull(this.testServiceFutureStub, "testServiceFutureStub");
67+
assertNotNull(this.testServiceStub, "testServiceStub");
68+
}
69+
70+
/**
71+
* Test template call to check for every exception.
72+
*/
73+
<E extends RuntimeException> void testGrpcCallAndVerifyMappedException(Status expectedStatus, Metadata metadata) {
74+
75+
verifyManualBlockingStubCall(expectedStatus, metadata);
76+
verifyBlockingStubCall(expectedStatus, metadata);
77+
verifyManualFutureStubCall(expectedStatus, metadata);
78+
verifyFutureStubCall(expectedStatus, metadata);
79+
}
80+
81+
private <E extends RuntimeException> void verifyManualBlockingStubCall(
82+
Status expectedStatus, Metadata expectedMetadata) {
83+
84+
StatusRuntimeException actualException =
85+
assertThrows(StatusRuntimeException.class,
86+
() -> TestServiceGrpc.newBlockingStub(this.channel).normal(Empty.getDefaultInstance()));
87+
88+
verifyStatusAndMetadata(actualException, expectedStatus, expectedMetadata);
89+
}
90+
91+
private <E extends RuntimeException> void verifyBlockingStubCall(Status expectedStatus, Metadata expectedMetadata) {
92+
93+
StatusRuntimeException actualException =
94+
assertThrows(StatusRuntimeException.class,
95+
() -> this.testServiceBlockingStub.normal(Empty.getDefaultInstance()));
96+
97+
verifyStatusAndMetadata(actualException, expectedStatus, expectedMetadata);
98+
}
99+
100+
101+
private <E extends RuntimeException> void verifyManualFutureStubCall(
102+
Status expectedStatus, Metadata expectedMetadata) {
103+
104+
final StreamRecorder<SomeType> streamRecorder = StreamRecorder.create();
105+
this.testServiceStub.normal(Empty.getDefaultInstance(), streamRecorder);
106+
StatusRuntimeException actualException =
107+
assertFutureThrows(StatusRuntimeException.class, streamRecorder.firstValue(), 5, TimeUnit.SECONDS);
108+
109+
verifyStatusAndMetadata(actualException, expectedStatus, expectedMetadata);
110+
}
111+
112+
113+
private <E extends RuntimeException> void verifyFutureStubCall(
114+
Status expectedStatus, Metadata expectedMetadata) {
115+
116+
StatusRuntimeException actualException =
117+
assertFutureThrows(StatusRuntimeException.class,
118+
this.testServiceFutureStub.normal(Empty.getDefaultInstance()),
119+
5,
120+
TimeUnit.SECONDS);
121+
122+
verifyStatusAndMetadata(actualException, expectedStatus, expectedMetadata);
123+
}
124+
125+
private void verifyStatusAndMetadata(
126+
StatusRuntimeException actualException, Status expectedStatus, Metadata expectedMetadata) {
127+
128+
assertThat(actualException.getTrailers())
129+
.usingRecursiveComparison()
130+
.isEqualTo(expectedMetadata);
131+
assertThat(actualException.getStatus())
132+
.usingRecursiveComparison()
133+
.isEqualTo(expectedStatus);
134+
}
135+
136+
}

0 commit comments

Comments
 (0)