6

The general question is how to simulate (as part of a JUnit suite of test cases) lack of network connectivity as this is an important consideration in some test cases. Is there a way to do so via a Java API (or via a JVM option) so that certain test cases can be run under network dis-connectivity? (simulated or real?).

The more specific case (if there is no generally applicable solution) is that I am doing a bunch of XML-file processing (including XSD-validation) and I need to ensure that nothing is fetched over the network, specifically, that the xsi:schemaLocation attributes values (hints) are not used and that all XSDs are actually obtained from the classpath. I am using a Validator with a custom LSResourceResolver that loads any XSDs that may be needed from the classpath.

I guess I could implement the resolveResource method of the LSResourceResolver so as to never return null (and therefore, so as to never fall back on the default behavior of opening a regular URI connection to the resource) but I am not sure whether that would be sufficient and at any rate I would feel more confident if I could run my JUnit tests in a simulated island-mode (without manually bringing down the interfaces on my machine).

UPDATE

The accepted answer, namely the -DsocksProxyHost approach provided exactly the solution I needed as the JUnit task can accept VM parameters (if fork is set to true) and so I can have the following in my Ant file:

<junit printsummary="true" showoutput="true" fork="true" maxmemory="256m">
    <jvmarg value="-DsocksProxyHost=127.0.0.1"/>
    ...

... wrapped inside contrib:if so I can control from the command line whether to run JUnit tests under conditions of network connectivity or not.

Marcus Junius Brutus
  • 26,087
  • 41
  • 189
  • 331
  • 2
    if you'd use a JVM option, that'd be an integration test. For a proper unit test, your network connectivity would be an isolated dependency that you can mock out. It sounds like you have a hard dependency to java network apis. – eis Feb 08 '15 at 17:31
  • Depends what is going on with your code but I'd either mock socket() calls ( see http://stackoverflow.com/questions/3202675/mocking-sockets-in-java-with-mockito for a discussion ) or run the test in a seperate VM if this wasn't appropriate- for instance if you are using an entirely seperate microservice which would not be altered by mocking in code under test – Vorsprung Feb 08 '15 at 17:52

2 Answers2

3

That's not what I would advise to do, but... you can try to use a security manager. By default JVM does not use a security manager, by setting -Djava.security.manager you will activate the default security manager. AFAIR, the default behaviour of the security manager is to block any connections (as long as the permission is not explicitly granted in security policy). But. You will get java.net.NetPermission Exception each time a connection will be blocked. You can also experience problems with local files access, reflection calls and so on.

Another possibility is to set the network proxy to a non-existent address, like -DsocksProxyHost=127.0.0.1. Then any TCP socket will try to use the SOCKS server and fail.

AGV
  • 414
  • 3
  • 7
1

Sniffy allows you to block outgoing network connections in your JUnit tests - it will throw a ConnectException whenever you try to establish a new connection.

@Rule public SniffyRule sniffyRule = new SniffyRule();

@Test
@DisableSockets
public void testDisableSockets() throws IOException {
    try {
        new Socket("google.com", 22);
        fail("Sniffy should have thrown ConnectException");
    } catch (ConnectException e) {
        assertNotNull(e);
    }
}

It also allows you to test how your application behaves with broken connectivity in runtime. Just add -javaagent:sniffy.jar=5559 to your JVM arguments and point your browser to localhost:5559 - it will open a web page with all discovered connections to downstream systems and controls to disable certain connections.

Sniffy connections console

Disclaimer: I'm the author of Sniffy

bedrin
  • 4,458
  • 32
  • 53
  • The documentation seems outdated in 2022. It says "just add this rule and this annotation" - but it seems that that's not enough. It also says "just grab that uber jar from our site and add it to your classpath" but there is no uber jar to download since 3.1.6 (only the source code is). After one hour of trying to get this thing to work as described in the documentation, I have given up and searching for something else. Neither the JUnit Rule nor the -javaagent stuff seems to work out of the box. The lib might be great when integrated from the beginning, just adding it does not work. – UniversE Jun 21 '22 at 14:12
  • @UniversE I appreciate your feedback and sorry it didn't work for you. The idea was to be able to add Sniffy to existing projects at any point of time - I will try to find some time to review the documentation. – bedrin Jun 21 '22 at 21:54