3

I'd like test classes to be aware if they are currently executed inside a Suite or not. I have a test suite which starts a server before all tests and shuts down the server after all tests, using ExternalResource. Works perfect. While writing new tests, I'd want to run a single test (or all from the same test class) to also start and stop the server. So I wanted those classes to become aware if they are currently executed inside a suite or not, and initiate server start accordingly. That seems to be impossible. The suite Description is never passed to @Rules or @ClassRules it seems. Neither can I get a reference to the current Runner that runs the current test.

Is there a way to do that?

Update due to the first proposed answer:

Please note that there are many other tests that may run before the test suite and after it. Therefore I can't rely on a JVM shut down. My main demand is that I'd like to run a single test from within my IDE (eclipse) right after writing the test, and still have the server start up and shut down. That should not happen for every test within the suite though.

sorrymissjackson
  • 2,395
  • 1
  • 19
  • 18

2 Answers2

1
  1. Make all your test classes extend some AbstractServerTest.
  2. Add @BeforeClass method in it to check if the server is already running and start it if it is not.
    • Remember that @BeforeClass will be called for every subclass, so the if-statement is necessary.
  3. When the last test finishes, the JVM will shut down, so as long as your server is running in the same JVM (and not as separate process), you don't need to do any cleanup.
    • If your server is running as a separate process, in your @BeforeClass method you can add a shutdownHook that will execute some command to stop the server when the JVM shuts down.
Jaroslaw Pawlak
  • 5,538
  • 7
  • 30
  • 57
  • Overall I agree with this approach, except for inheritance, the usual problems apply with that. You could instead do it with a `Rule` and avoid inheritance completely – tddmonkey Aug 16 '16 at 11:10
  • @tddmonkey Doesn't it require to add this rule to every class? In both cases all the test classes have to be changed, but in my opinion `extends AbstractServerTest` is simpler than adding extra field with annotation, which would be a noise among other fields. Also you have to remember to make field public, otherwise it will be simply ignored. With inheritance you cannot make such mistake. – Jaroslaw Pawlak Aug 16 '16 at 11:16
  • Could work, but not in my case. There a literally hundreds of other JUnit tests that may run before or after the tests using the server. Meaning the JVM will not necessarily shut down after the last test using the server finished. – sorrymissjackson Aug 16 '16 at 14:04
  • @sorrymissjackson I don't see a problem - if other tests don't need the server, there is no harm of having it running. The common practice on top of that is to specify tests suites in your maven/gradle so you can run both suites (those that need the server and those that don't) separately. – Jaroslaw Pawlak Aug 16 '16 at 14:06
  • @JaroslawPawlak The server mimics the production environment for integration testing, meaning it could start sending out emails (or at least try to) depending on certain events. So that would be a last resort solution. Also, right now I just want to know if a test can be aware of it's suite. – sorrymissjackson Aug 16 '16 at 14:10
  • @JaroslawPawlak I think you're missing the point - you're right that in both cases the tests must change, but with a rule you're not tying yourself into an inheritance tree - they're composition. If you /need/ to extend another class your solution doesn't allow for that but a rule does. Also if you forget to make the rule public the test will fail, so I don't see how you can forget to make it public – tddmonkey Aug 16 '16 at 17:46
  • @tddmonkey The point is that it is a matter of preference. You normally don't add inheritance to test classes unless in cases like this, which means that you are very unlikely to hit a problem when you want to extend two different classes. If you forget to make Rule public in one test, the test will fail if you run it alone, if you run it in a group it will be green because other Rule in another class is public. A few weeks/months later it might be difficult to figure out why this test run alone is red. – Jaroslaw Pawlak Aug 16 '16 at 18:16
0

May I simply suggest to use port-probing and check if a port is already bound within a JUnit test-rule (or a @Before/@BeforeClass annotated method) and only initialize the service if the port is still available. This way you can start the service externally or within the suite and reuse it within your test or initialize it before the test if the port is still available. This of course requires a fixed port assignment which is only used for the specific services needed while testing.

As you obviously performing an integration test, you might also be interested in how to setup Maven or Gradle to execute tests within the test integration phase automatically.

Community
  • 1
  • 1
Roman Vottner
  • 12,213
  • 5
  • 46
  • 63