mdarwin
mdarwin

Reputation: 2394

what's the simplest way to intercept http calls from within a junit?

We have some tests, which we run from a shell script. They make calls to system A, which in turn calls system B. We therefore have 3 separate JVMs. These tests are fully automated and run without any human intervention on a jenkins system.

As part of my test, I want to intercept the calls from A to B and check various things about the content. The call still needs to reach B, and B's response needs to be returned unaltered to A.

System A has configuration to tell it where B is. They are all running on my local machine, so the obvious option is to start an http server (perhaps jetty) from within the test, configure A to talk to my temporary server, then when I run my test, the server will see all traffic sent from A to B. It needs to then pass those requests to B, get the response, and return that response back to A. The unit test then needs to see the contents of each request as a String, and do some checks on it.

I have done something similar in the past using jetty. My previous stub solution did something very similar: but instead of proxying the calls to another system, it simply checked the request and returned a dummy response. We are restricted to using jetty 6.1 - using another version would be do-able, but a PITA.

I think that jetty could be the best solution. I could do it very simply by extending AbstractHandler, then creating a new http call to system B. But it would be a bit messy. Is there a simple, standard way of doing this?

Upvotes: 2

Views: 2587

Answers (1)

jpmc26
jpmc26

Reputation: 29904

The simplest way is don't.

First, what you're describing are clearly not unit tests. A unit test is one that tests a small bit of code in isolation from the rest of the application, never mind external resources. Instead, you're testing the application as a whole, and the application has external dependencies. That's fine, but these tests fall into either the integration or functional test category. (In practice, you might still use a unit testing framework to write those kinds of tests, but the distinction is important.)

Second, what do you actually hope to gain by doing this? How is it going to improve the reliability or quality of application A? It's highly likely that it won't, and the added complexity of trying to maintain the set up and extra assertions are actually going to make everything less maintainable.

So here is what I would do:

  1. Write a series of unit tests on the individual bits of logic within applications A and B. These will test the logic in isolation. (I would recommend that you execute the unit tests first and separately, and then when unit tests fail, your build can fail fast before executing the integration and functional tests. Integration and functional tests will be slower and more cumbersome, so this notifies you of problems more quickly. Up to you on that point, though.)
  2. Write a series of integration or functional tests that check that application B gives the correct output given a specific input.
  3. Write a series of integration or functional tests on the input and output of A. When writing them, have it just call the real B and assume that B is working as intended. If it isn't, your application B tests will pick up on it, and you'll have some extra failures in the application A tests that you can ignore until B is fixed.

You don't have to mock everything. Trying to do so will cause you more trouble than it will save. Overly complex tests will be a net loss.

Upvotes: 2

Related Questions