pact-foundation / pact-jvm

JVM version of Pact. Enables consumer driven contract testing, providing a mock service and DSL for the consumer project, and interaction playback and verification for the service provider project.
https://docs.pact.io
Apache License 2.0
1.08k stars 478 forks source link

Need to force a timeout to test socket settings #1301

Open iWantToKeepAnon opened 3 years ago

iWantToKeepAnon commented 3 years ago

I have a camel route that reads from JMS and writes to HTTP(S)4. I am setting connectTimeout and socketTimeout via the query parameters. I would like for pact HTTP mock server to sleep and force a timeout. After the "willRespondWith" call, I don't see a way to add a delay.

Is there a way to force a timeout w/o overloading MockHttpServer? Maybe adding a timeout/sleep call to the config DSL? I searched online and didn't find an example of this testing scenario.

thx.

uglyog commented 3 years ago

This is not really what Pact is designed to do. What are you trying to accomplish? If you want to inject latency into your tests, there are other tools that can do this.

iWantToKeepAnon commented 3 years ago

I guess this is behavioral testing and not functional testing. I own a webservice and our client is an external 3rd party, so I wrote pact tests in my IT module to test from the client perspective. When we started seeing timeouts from the client I tried to write a test to simulate that. Yes there are other tools but 100% of my tests are in pact and I was wanting to keep it that way if possible.

If there was a "willRespondWith.delay(x)" or "willRespondWith.bean(x) / .lambda({x})" etc... that would introduce a lot of flexibility with this kind of "not-intended" testing.

Just some thoughts, thanks for replying.

P.S. I did find an ugly hack that created a mock server that causes a timeout for the first request and a normal request the second time.

   // This ugly internal class is to help force a timeout test (wish I could figure out how to make pact do this internally. TODO?)
   class TimeoutMockServer extends MockHttpServer {
      int called;

      TimeoutMockServer(RequestResponsePact pact, MockProviderConfig config) {
         super(pact, config);
         this.called = 0;
      }

      @Override
      public void handle(HttpExchange exchange) {
         if ("OPTIONS".equals(exchange.getRequestMethod()) && exchange.getRequestHeaders().containsKey("X-PACT-BOOTCHECK")) {
            super.handle(exchange);

         } else {
            log.info("TimeoutMockServer.handle: called = {}", called);
            if (++ called > 1) {
               // If the client calls again (and camel should), let it progress normally.
               super.handle(exchange);
               return;
            }

            try {
               log.debug("Sleeping {} ms to create a timeout", restTimeout + 5000);
               Thread.sleep(restTimeout + 5000); // force a timeout failure
               exchange.sendResponseHeaders(200, 0); // This should come in too late, unless client didn't timeout.

            } catch (Exception e) {
               log.error("Failed to generate response: {}", e);
            }

         }
      }
   }
uglyog commented 3 years ago

Why do you say this is an ugly hack? Extending behaviour by sub-classing is one of the principles of object-orientated programming. If it works for you it is a valid solution.

iWantToKeepAnon commented 3 years ago

Why do you say this is an ugly hack?

Oh well, I guess b/c it doesn't use the fluent api but you're right. I needed to add behavior and I could w/ sub-classing. Thx for the feedback : )