3

I am developping a Swing application that needs to communicate with a distant HTTP server. That application can be potentially used behind proxies.

I must then : - detect automatically network proxy (potentially several on the same network) - let the user manually enter a proxy configuration.

I want to write an integration test to validate thoses aspects, without having to install proxies on every CI machines and every developper machine. How I see things :

  • integration test (with junit) start an "embedded" proxy (@BeforeClass) and a somewhat dummy http server
  • my tests (@Test)
    • test that this proxy can be detected automatically and open a connection to my dummy http server and successfully retrieve datas from it
    • manually set the proxy and perform the same test as above

I have heard about the "littleProxy" component but didn"t tried it yet.

Can anyone shed some advice / help / guidance regarding the best approach to solve my problem ?

M'λ'
  • 631
  • 7
  • 18
  • On second thought, and after reading McDowell answer, I finally taken the mock approach ! – M'λ' Dec 21 '12 at 10:12

1 Answers1

2

I would consider whether you are testing the right thing. You don't need to test proxy servers or Java's network classes.

Consider this utility type for reading data from a URL:

public final class Network {
    public interface UrlOpener {
        public InputStream open(URL url) throws IOException;
    }

    private static UrlOpener urlOpener = new UrlOpener() {
        public InputStream open(URL url) throws IOException {
            return url.openStream();
        }
    };

    public static InputStream openUrl(URL url) throws IOException {
        return urlOpener.open(url);
    }

    public static void setUrlOpener(UrlOpener urlOpener) {
        Network.urlOpener = urlOpener;
    }
}

This can be used as an abstraction layer between your code and Java's network I/O:

public class SomeType {
    public void processData(URL url) throws IOException {
        InputStream input = Network.openUrl(url);
        // process the data
    }
}

Your tests use this layer to mock out the data:

@Before public void setup() throws IOException {
    final URL mockUrl = this.getClass().getResource("/foo/bar.txt");
    Network.UrlOpener opener = Mockito.mock(Network.UrlOpener.class);
    Answer<InputStream> substituteUrl = new Answer<InputStream>() {
        public InputStream answer(InvocationOnMock invocation) throws Throwable {
            return mockUrl.openStream();
        }
    };
    Mockito.when(opener.open(Mockito.any(URL.class))).then(substituteUrl);
    Network.setUrlOpener(opener);
}

@Test public void testSomething() throws IOException {
    SomeType something = new SomeType();
    something.processData(new URL("http://example.com"));
}

This saves any mucking around with firewalls etc.

In order for this approach to work you would want to have confidence in a set of recorded transactions from real servers to use in your tests.

This approach can be complemented with a dedicated machine running more comprehensive integration tests.

McDowell
  • 102,869
  • 29
  • 193
  • 261
  • You are right : why testing java proxy related classes ? ;) Thank you for your example code ! – M'λ' Dec 21 '12 at 10:10