Given the requirement that every junit test have to run in the following wrapper:
#Test
public void testFooBar() {
SpecialLogic.runWith(new SpecialLogic("blah", "foo", ANYTHING), () -> {
// my test
});
}
I am trying to avoid adding SpecialLogic.runWith(...) for each test.
Is there any possibility by using #BeforeEach or any other way?
Otherwise, there is much of duplicated code:
#Test
public void testFooBar_2() {
SpecialLogic.runWith(new SpecialLogic("blah", "foo", ANYTHING), () -> {
// my test logic 2
});
}
#Test
public void testFooBar_3() {
SpecialLogic.runWith(new SpecialLogic("blah", "foo", ANYTHING), () -> {
// my test logic 3
});
}
There are two ways of doing this:
Write your custom Runner, all the tests will have to run with this runner.
This may be inappropriate if you already use another runner (say for spring or mockito)
Write your own Rule. The rule is a little bit newer way of doing what you've asked for,
and it doesn't "occupy" the slot of a runner which can be only one.
public final class SampleRule implements TestRule {
#Override public Statement apply(final Statement base,
final Description description) {
return new Statement() {
#Override public void evaluate() throws Throwable {
// do your stuff before actually running the test
try {
base.evaluate(); // This line actually runs the test.
} finally {
// do your stuff after running a test
}
}
};}}
Here is one of numerous guides for writing Rules:
Looks like you should implement your own TestRunner to wrap your custom logic around each test method call. There is an article over at Baelung explaining how this works.
#Before and #After? It won't use closures but should be functionally the same.
https://junit.org/junit4/javadoc/latest/org/junit/Before.html
https://junit.org/junit4/javadoc/latest/org/junit/After.html
Related
I want to mock that some code is being called when a CompletableFuture has completed successfully.
I have this class:
public class MyClassImplementRunner implements Runnable {
private final String param1;
public MyClassImplementRunner(String param1) {
this.param1 = param1;
}
public static CompletableFuture<Void> startAsync(String param1) {
return CompletableFuture.runAsync(
new MyClassImplementRunner(param1)).whenComplete(
(response, throwable) -> {
//some code when complete
});
#Override
public void run () {
//the runnable code
}
}
}
In my Junit (using Mockito and Java 8), I need to mock that
//some code when complete
is called when Future is completed successfully.
Could you provide some indications on how to achieve this?
Extract the code you execute in whenComplete to a field and provide a constructor to replace it.
class Runner implement Runnable {
private final String param;
private final BiConsumer<Void, Throwable> callback;
public Runner(String param) {
this.param = param;
this.callback = this::callbackFunction;
}
Runner(String param, BiConsumer<Void, Throwable> callback) {
this.param = param;
this.callback = callback;
}
public void run() {
CompletableFuture.runAsync(task).whenComplete(callback);
}
private void callbackFunction(Void result, Throwable throwable) {
//some code when complete
}
}
The test will look as follows:
class RunnerTest {
#Test
void test() {
new Runner("param", (response, throwable) -> /* mocked behavior */).run();
}
}
My first inclination is not to mock this: It looks like startAsync is a part of MyClassImplementRunner's public API, and that you should be testing these pieces together. In a test class like MyClassImplementRunnerTest, it makes sense to treat the system under test as MyClassImplementRunner without trying to split it up. Otherwise, it's very easy to lose track of what you're testing, including what is real versus what is a mock.
If there is any external condition that MyClassImplementRunner is looking for, you can mock that dependency, which would likely cause your CompletableFuture to return immediately; however, you've only shown us a single String parameter.
That said, it's possible that startAsync contains logic that you'd like to test exhaustively without a real MyClassImplementRunner. In that case, you could create an overload for testing, possibly with limited visibility or test-only annotations to indicate that it shouldn't be called in production.
public static CompletableFuture<Void> startAsync(String param1) {
return startAsync(new MyClassImplementRunner(param1);
}
/** Package-private, for a test class in the same package. */
#VisibleForTesting static CompletableFuture<Void> startAsync(Runnable task) {
return CompletableFuture.runAsync(task).whenComplete(
(response, throwable) -> {
//some code when complete
});
}
By splitting this up, you can now run startAsync(new Runnable()) in tests to simulate an instantly-succeeding task, and run startAsync(() -> { throw new RuntimeException(); }) to simulate an instantly-failing task. This allows you to test startAsync independently from MyClassImplementRunner.
It may not seem wise to refactor for testing or to introduce test-only methods, and this is a fair assessment: Purely speaking, MyClassImplementRunner should be tested exactly as consumers would run it, without mocking. However, if you're saying it is much more convenient in tests to run with a different Runnable than MyClassImplementRunner, you are in control of the code and you can prepare for this by including the appropriate flexiblity ("testing seam") in the code you control. In fact, if startAsync is a separate-enough method that it can take an arbitrary Runnable, you may choose to separate it out to be a separate method with separate testing.
I have a test like this:
#Test public void testInfinite() {
while (true) {runSomeOtherTest();waitForSomeSignal();}
We have a spring context which takes a while to initialize - and with the above test and hotswapping - it means I can debug changes in seconds rather than waiting for a restart.
However, obviously checking this into the CI system is a bit of a problem, and of course something I've accidentally done several times. I'm wondering if it's possible (without changing the testrunner, because we are already using a custom one, that's hard to modify) to determine if it's the only test running. eg I want to be able to say
#Test public void testInfinite() {
if (!testIsTheOnlyTestWhichWillBeRun()) return; ...
So, bottom line - what I'm looking for is that if I right click on exactly that test and say run, in the IDE - it will do that - in all other cases - eg I right click and run the whole class - or I do it from gradle, or from CI - the test does nothing and just returns immediately.
You can evaluate a System property:
#Test public void testInfinite() {
if (!"true".equals(System.getProperty("junit.runloop"))) {
return;
}
}
In your IDE/local run, you can then run the test with -Djunit.runloop=true.
To not polute the test cases themselves, you could write a JUnit rule that does this:
public class TestInfinite implements TestRule {
#Override
public Statement apply(Statement base, Description description) {
return new Statement() {
public void evaluate() throws Throwable {
do {
base.evaluate();
} while ("true".equals(System.getProperty("junit.runloop")));
}
};
}
}
So in your test, you can attach them:
public class YourTest {
#Rule public TestInfinite = new TestInfinite();
#Test public void testInfinite() {
// this will be run once if property is not set,
// in an endless loop if it is
}
}
I have a bunch of integration tests that need to have a database populated before running. This task takes about 30 minutes, so it is not feasible to run it before every test.
I'm using junit and I'd like to be able to annotate this one class with something so that it runs and completes before the others start. Is this possible?
(most of the annotations I found only work on methods, e.g. #Rule)
I've done this in the past by adding setup and teardown functions to the individual test classes, annotated with #BeforeClass and #AfterClass.
#BeforeClass
public static void setupBeforeClass() {
DatabasePopulater.populate();
}
#AfterClass
public static void tearDownAfterClass() {
DatabasePopulater.dePopulate();
}
If more than one test class requires the same setup to be done, the setup function can do a kind of reference counting to make sure they only do their work the first time it's called:
public class DatabasePopulater {
AtomicInteger invocations = new AtomicInteger();
....
public static void populate() {
if (0 == ivocations.getAndIncrement()) {
// Actually populate DB
}
}
public static void dePopulate() {
if (0 == ivocations.decrementAndGet()) {
// Actually clear DB
}
}
If you are using something like ant/gradle to execute the test suite, you could separate out the db population into a standalone java program and then have a depends="populateDB" on the junit task.
I am implementing some tests for an existing Java Swing application, so that I can safely refactor and extend the code without breaking anything. I started with some unit tests in JUnit, since that seems the simplest way to get started, but now my priority is to create some end-to-end tests to exercise the application as a whole.
I am starting the application afresh in each test by putting each test method in a separate test case, and using the fork="yes" option in Ant's junit task. However, some of the use cases I would like to implement as tests involve the user exiting the application, which results in one of the methods calling System.exit(0). This is regarded by JUnit as an error: junit.framework.AssertionFailedError: Forked Java VM exited abnormally.
Is there a way to tell JUnit that exiting with a return code of zero is actually OK?
The library System Rules has a JUnit rule called ExpectedSystemExit. With this rule you are able to test code, that calls System.exit(...):
public class MyTest {
#Rule
public final ExpectedSystemExit exit = ExpectedSystemExit.none();
#Test
public void systemExitWithArbitraryStatusCode() {
exit.expectSystemExit();
/* the code under test, which calls System.exit(...)
* with an arbitrary status
*/
}
#Test
public void systemExitWithSelectedStatusCode0() {
exit.expectSystemExitWithStatus(0);
//the code under test, which calls System.exit(0)
}
}
System Rules needs at least JUnit 4.9.
Full disclosure: I'm the author of System Rules.
How I deal with that is to install a security manager that throws an exception when System.exit is called. Then there is code that catches the exception and doesn't fail the test.
public class NoExitSecurityManager
extends java.rmi.RMISecurityManager
{
private final SecurityManager parent;
public NoExitSecurityManager(final SecurityManager manager)
{
parent = manager;
}
public void checkExit(int status)
{
throw new AttemptToExitException(status);
}
public void checkPermission(Permission perm)
{
}
}
And then in the code, something like:
catch(final Throwable ex)
{
final Throwable cause;
if(ex.getCause() == null)
{
cause = ex;
}
else
{
cause = ex.getCause();
}
if(cause instanceof AttemptToExitException)
{
status = ((AttemptToExitException)cause).getStatus();
}
else
{
throw cause;
}
}
assertEquals("System.exit must be called with the value of " + expectedStatus, expectedStatus, status);
Could you abstract out the "system exiting" into a new dependency, so that in your tests you could just have a fake which records the fact that exit has been called (and the value), but use an implementation which calls System.exit in the real application?
If anybody needs this functionality for JUnit 5, I've written an extension to do this. This is a simple annotation you can use to tell your test case to expect and exit status code or a specific exit status code.
For example, any exit code will do:
public class MyTestCases {
#Test
#ExpectSystemExit
public void thatSystemExitIsCalled() {
System.exit(1);
}
}
If we want to look for a specific code:
public class MyTestCases {
#Test
#ExpectSystemExitWithStatus(1)
public void thatSystemExitIsCalled() {
System.exit(1);
}
}
I have a junit testCase class with multiple test methods in it ( As requirement , we don't want to create separate class for each test.)
I wanna create a tearDown type method for EACH test method , which will run specifically for that test. Not for ALL test.
My problem is , in many tests i Insert record in database, test it and delete it after test.
But, If a test fails mid way , control don't reaches till end my dummy record ain't deleting.
I think only ONE tearDown() is allowed for one class, and this tearDown() don't know what object/record i created or inserted and what to delete!!!
I want to create a tearDown() or #After method just for one specific test. Something like finally{} in java for each method.
For Eg:
public class TestDummy extends TestCase {
public void testSample1(){
InsertSomeData1();
assertFalse(true);
runTearDown1();
}
public void testSample2(){
InsertSomeData2();
assertFalse(true);
runTearDown2();
}
public void runTearDown1(){
deleteDummyDatafromTestSample1....
}
public void runTearDown2(){
deleteDummyDatafromTestSample2....
}
}
Here control will never go to runTearDown1() or runTearDown2() and I don't a one common tearDown() because it won't know what data I inserted and thats specific to each method.
It seems your test relies on a fixed database, and future tests will break if your current test breaks. What I'd recommend is not to focus on this particular problem (a test-specific tearDown method that runs for each test), but your main problem - borken tests. Before your test run, it should always work with a clean database, and this should be the case for each test. Right now, your first test has a relationship with the second (through the database).
What the right approach would be is that you recreate your database before each test, or at the very least reset it to a basic state. In this case, you'll want a test like this:
public class TestDummy {
// this code runs (once) when this test class is run.
#BeforeClass
public void setupDatabase() {
// code that creates the database schema
}
// this code runs after all tests in this class are run.
#AfterClass
public void teardownDatabase() {
// code that deletes your database, leaving no trace whatsoever.
}
// This code runs before each test case. Use it to, for example, purge the
// database and fill it with default data.
#Before
public void before() {
}
// You can use this method to delete all test data inserted by a test method too.
#After
public void after() {
}
// now for the tests themselves, we should be able to assume the database will
// always be in the correct state, independent from the previous or next test cases.
#Test
public void TestSample2() {
insertSomeData();
assertTrue(someData, isValid());
}
}
Disclaimer: JUnit 4 tests (using annotations), might not be the right annotations, might not even be the right answer(s).
You could have smth like this:
interface DBTest {
void setUpDB();
void test();
void tearDownDB();
}
class DBTestRunner {
void runTest(DBTest test) throws Exception {
test.setUpDB();
try {
test.test();
} finally {
test.tearDownDB();
}
}
}
public void test48() throws Exception {
new DBTestRunner().runTest(new DBTest() {
public void setUpDB() {...}
public void test() {...}
public void tearDownDB() {...}
});
}
#iluxa . Gr8.. Your solution is perfect!!! In one test class i created two tests test48 and test49 (same as required in my code above testSample1 and testSample2) and viola! every test method now gets its own setup() and tearDown. Only this solution looks little complicated as need to use DBTestRunner in each method, but I don't see any better solution. I was thinking Junit may have some direct solution. like #After or tearDown() with some parameter or something.
Tks a lot.
Use MethodRule:
public class MyRule implements MethodRule {
#Override
public Statement apply(final Statement base, FrameworkMethod method, Object target) {
return new Statement() {
#Override
public void evaluate() throws Throwable {
try {
base.evaluate();
} catch (AssertionError e) {
doFail();
} finally {
doAnyway();
}
}
};
}
}
Then declare it in your test class:
public class TestDummy{
public MethodRule rule = new MyRule();
......
}