Fadelis / grpcmock

A gRPC Java testing tool to easily mock endpoints of gRPC services for IT or Unit testing
http://grpcmock.org
Apache License 2.0
144 stars 13 forks source link

Server returns UNIMPLEMENTED when Junit @Test uses timeout #8

Closed RobinNoHood closed 3 years ago

RobinNoHood commented 3 years ago

First of all thanks for this library, it's fantastic and exactly what we were looking for. Super easy to use once we got the setup/annotations right.

There is however one strange issue I noticed recently in one of our integration tests: When the test (Junit 4) specifies a timeout (e.g. via @Test(timeout = 5000)), then all calls to the mock server return Code.UNIMPLEMENTED. As soon as I remove the timeout, the test works fine. The timeout value doesn't seem to matter in this case, the test is nowhere close to actually timing out.

I haven't had the time to create a minimal reproducible example yet, but maybe someone has an idea what might be causing this behavior.

Versions: org.grpcmock:grpcmock:0.5.3 org.grpcmock:grpcmock-spring-boot:0.5.3

Fadelis commented 3 years ago

Hi @RobinNoHood, if you read the [javadoc](https://junit.org/junit4/javadoc/4.12/org/junit/Test.html#timeout()) for the timeout variable you'll see a bold notice regarding thread safety. And that's why you're observing this behaviour - when you add the timeout, that test method is run on a different thread and if you're using static GrpcMock methods to configure the stubs, they will be configured for the incorrect GrpcMock ThreadLocal instance. So either you'd need to use different mechanisms to achieve tests' timeout or you'd need to inject/autowire the running/default GrpcMock bean and use that instance to register the stubs:

@Autowired
private GrpcMock grpcMock;

@Test(timeout = 1000L)
public void someTest() {
  grpcMock.register(unaryMethod(HealthGrpc.getCheckMethod())
        .willReturn(response(response)));
}
RobinNoHood commented 3 years ago

Oh I must have missed that part, but it makes sense obviously (although I did try it with a Timeout rule as suggested in the documentation which didn't seem to make any difference in this case). I'll try your suggestion then, thanks a lot!