-
Notifications
You must be signed in to change notification settings - Fork 63
#7: Support for in-process transport for testing #44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
#7: Support for in-process transport for testing #44
Conversation
Signed-off-by: andreilisa <[email protected]>
855d267 to
296653e
Compare
...test/src/main/java/org/springframework/grpc/test/InProcessApplicationContextInitializer.java
Outdated
Show resolved
Hide resolved
...test/src/main/java/org/springframework/grpc/test/InProcessApplicationContextInitializer.java
Outdated
Show resolved
Hide resolved
| public static void shutdown() { | ||
| if (grpcChannel != null) | ||
| grpcChannel.shutdownNow(); | ||
| if (grpcServer != null) | ||
| grpcServer.shutdownNow(); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe users should not have to call to startup or should down from their test classes.
Instead, we can leverage a post-processor to handle the shutdown process.
I think this TestcontainersLifecycleApplicationContextInitializer is a good reference
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I am agree with you about this point, and also I think that an ApplicationListener on ContextClosedEvent achieves the purpose of not requiring users to manually handle the lifecycle, specifically shutdown.
ced3c2d to
296653e
Compare
Signed-off-by: andreilisa <[email protected]>
|
Thanks for the fixes. I'm still waiting for I think we should have a sample test as well. The existing samples should now be enabling this by default? So we could slip one in there. |
|
@dsyer I changed the property to |
a107df3 to
cfb847c
Compare
|
|
||
| @Override | ||
| public void initialize(ConfigurableApplicationContext applicationContext) { | ||
| GrpcProperties grpcProperties = new GrpcProperties(applicationContext.getEnvironment()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally I don't think class GrpcProperties is necessary
| @Override | ||
| public void initialize(ConfigurableApplicationContext applicationContext) { | ||
| GrpcProperties grpcProperties = new GrpcProperties(applicationContext.getEnvironment()); | ||
| if (grpcProperties.isInProcessEnabled() && isJarOnClasspath()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could check the reversed conditions and return early
| } | ||
| } | ||
|
|
||
| private boolean isJarOnClasspath() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider re-use existing method ClassUtils.isPresent
| import static org.assertj.core.api.Assertions.assertThat; | ||
| import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; | ||
|
|
||
| class InProcessApplicationContextInitializerTests { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this test class be in spring-grpc-test module instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It depends if the test jar depends on Spring Boot or not. I'm happy for it to be here for now anyway -it could also be a nested class inside the existing GrpcServerIntegrationTests (which I see below you already have, so maybe we don't need this one at all?).
I’m not sure I like the sound of that. There’s nothing like it in the whole Spring Boot ecosystem as far as I know. Did you try it in a sample and it wasn’t available in a test? |
I haven't tried it in a sample yet, let me try it and I will do the changes(using metadata file for this property) to match the ecosystem pattern as well. |
Signed-off-by: andreilisa <[email protected]>
cfb847c to
4493635
Compare
|
Hello, @dsyer can you please check one more time the changes ? Now the PR should look better. |
|
I added a couple more comments. If you could squash and rebase that will help as well, please. |
I cannot see your comments |
...test/src/main/java/org/springframework/grpc/test/InProcessApplicationContextInitializer.java
Outdated
Show resolved
Hide resolved
...test/src/main/java/org/springframework/grpc/test/InProcessApplicationContextInitializer.java
Outdated
Show resolved
Hide resolved
| /* | ||
| * @author Andrei Lisa | ||
| */ | ||
| public class InProcessApplicationContextInitializer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a special reason this is an ApplicationContextInitializer? What is the expected usage? I was sort of hoping that a user would be able to easily write an integration test that uses the in-process channel instead of the tcp one. Doesn't that mean we should make it look as much like the existing GrpcServerLifecycle pattern?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe ApplicationContextInitializer is a better fit here, as it allows us to set up a simple in-process channel builder directly at application startup and ensures that it’s automatically shut down when the process ends. This approach keeps things lightweight and aligns well with the purpose of the in-process channel, as we don’t need the full lifecycle management that GrpcServerLifecycle provides.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I disagree, and I'm not really sure I want to merge this yet. It works up to a point, but it doesn't stop the tcp server starting, which feels odd to me (I was hoping for a drop in replacement). It's also an unusual way to implement this kind of feature, and I'm not convinced it won't create problems down the road. Looking at the test containers support was a good suggestion, so I'd like to understand what we are missing there before we do anything else here.
| import static org.assertj.core.api.Assertions.assertThat; | ||
| import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; | ||
|
|
||
| class InProcessApplicationContextInitializerTests { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It depends if the test jar depends on Spring Boot or not. I'm happy for it to be here for now anyway -it could also be a nested class inside the existing GrpcServerIntegrationTests (which I see below you already have, so maybe we don't need this one at all?).
|
|
||
| @Nested | ||
| @SpringBootTest(properties = { "spring.grpc.server.host=0.0.0.0", "spring.grpc.server.port=0", | ||
| "spring.grpc.inprocess.enabled=true" }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the same test as WithInProcessEnabled? Probably we can just have one (and not set the property - just use the default).
| try { | ||
| String serverName = InProcessServerBuilder.generateName(); | ||
|
|
||
| Server grpcServer = InProcessServerBuilder.forName(serverName).directExecutor().build().start(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are starting this server without registering any services. This is a bug, and it should have had a test. Feels like maybe a sign that we would be better sticking more closely to the GrpcServerFactory pattern. I'm still open to not doing that, but there has to be a test, and the services have to get registered, at a minimum. What about interceptors? They probably need to get registered as well (maybe with exceptions for testing).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you are right and also I’m aware of the missing service registration and encountered the same issue in testing. I agree that this indicates a need to align more closely with the GrpcServerFactory pattern, especially for consistency in managing service and interceptor registration. At a minimum, I’ll ensure that services are properly registered and that we have a test to validate this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dsyer Can you please check the changes again ? II implemented a factory for the in-process channel that now ensures the correct registration of services, which resolves the bugs we encountered earlier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dsyer Hello, what do think about this PR ?
Signed-off-by: andreilisa <[email protected]>
|
Closing in favour of 2df6c37. |
This pull request introduces support for in-process transport for gRPC, facilitating efficient testing of gRPC services within the same process.