i got a question if it is possible to create a Runner for this:
#RunWith(MyRunner.class)
public class Class1Test {
#Test public void test2() {
doSomething();
assertTrue(something);
doSomethingElse();
assertTrue(somethingElse);
}
}
The Runner should make a log after every call / assertion in the test.
public class MyRunner extends BlockJUnit4ClassRunner {
public MyRunner(Class<?> klass) throws InitializationError {
super(klass);
}
/* Here should be an method that just executed the calls/assertions but log everything */
}
That's not possible because the test methods aka Statements are the smallest units visible to JUnit.
You can log the calls to JUnit's Assertclass by wrapping it and doing the logging in your wrapper.
Related
How can I execute a method once before all tests in all classes start?
I have a program that needs a system property to be set before any test start. Is there any way to do that?
Note: #BeforeClass or #Before are used just for the same test class. In my case, I'm looking for a way to execute a method before all test classes start.
To setup precondition to your test cases you can use something like this -
#Before
public void setUp(){
// Set up you preconditions here
// This piece of code will be executed before any of the test case execute
}
if you need to run that method before the start of all test you should use the annotation #BeforeClass or if you need to execute the same method every time you will execute a test method of that class you must use #Before
f.e
#Before
public void executedBeforeEach() {
//this method will execute before every single test
}
#Test
public void EmptyCollection() {
assertTrue(testList.isEmpty());
}
You can make use of a Test Suite.
The test suite
#RunWith(Suite.class)
#Suite.SuiteClasses({ TestClass.class, Test2Class.class, })
public class TestSuite {
#BeforeClass
public static void setup() {
// the setup
}
}
and, the test classes
public class Test2Class {
#Test
public void test2() {
// some test
}
}
public class TestClass {
#Test
public void test() {
// some test
}
}
Or, you can have a base class which handles the setup
public class TestBase {
#BeforeClass
public static void setup() {
// setup
}
}
and, then the test classes can extend the base class
public class TestClass extends TestBase {
#Test
public void test() {
// some test
}
}
public class Test2Class extends TestBase {
#Test
public void test() {
// some test
}
}
However, this will call the setup method in TestBase for all its subclasses everytime each of them executes.
I'm using IntelliJ IDEA CE 2018.3 and JUnit 4.12.
I have a test class that looks like this:
#RunWith(HierarchicalContextRunner.class)
public class TestClass {
#BeforeClass
public static void beforeAll() {
//start a server for all tests to hit
}
#Before
public void before() {
//init a common request object for each test
}
#Test
public void itShouldHaveSomeCommonProperty() {
//check some common thing
}
public class SomeSubTestClass {
#Before
public void before() {
//do some test case-specific setup
}
public class SomeOtherSubTestClass {
#Test
public void itShouldDoSomething() {
//hit the service and assert something about the result
}
}
}
}
When I tell IntelliJ to run the class, everything works as expected. However, if I want to just run the itShouldDoSomething test (which I'm doing by setting up a run configuration that targets the SomeOtherSubTestClass class), the beforeAll method is not executed. Both of the before methods are executed in the correct order, but not the static beforeAll method.
Am I misunderstanding something, or is this a bug?
It is not a bug.
The beforeAll method is static and therefore tied to the class and not the instance. This is why it is not executed when calling tests in inner classes or sub-classes.
To ensure it being called you would have to define a #BeforeClass method in each of your inner classes which then call the method on the outer class.
Currently for tests I'm using TestExecutionListener and it works just perfect
public class ExecutionManager extends AbstractTestExecutionListener {
#Override
public void beforeTestClass(TestContext testContext) throws Exception {
System.out.println("beforeClass");
}
#Override
public void afterTestClass(TestContext testContext) throws Exception {
System.out.println("afterClass");
}
}
Test classes:
#RunWith(SpringJUnit4ClassRunner.class)
#TestExecutionListeners(ExecutionManager.class)
public final class TC_001 {
#Test
public void test() {
System.out.println("Test_001");
}
}
#RunWith(SpringJUnit4ClassRunner.class)
#TestExecutionListeners(ExecutionManager.class)
public final class TC_002 {
#Test
public void test() {
System.out.println("Test_002");
}
}
When I include those tests in test suite, beforeTestClass(TestContext testContext) and afterTestClass(TestContext testContext) methods are executed for each test class, what is quite logical:
#RunWith(Suite.class)
#Suite.SuiteClasses({
TC_001.class,
TC_002.class
})
public final class TS_001 {
}
Is there anything like SuiteExecutionListener (TestExecutionListener for suites)?
Basically I need non-static #BeforeClass and #AfterClass for suite
OR
In ExecutionListener I need to find out what class has been launched: case or suite. For this purpose I can:
analyze StackTrace and get calling class
use Reflection.getCallerClass(int i) (which is deprecated)
pass caller class to ExecutionManager (By the way, how can I do that? Is it possible to put Object into TestContext like in Android Bundle?)
But I don't really like those solutions. SuiteExecutionListener is much more preferable
Thank you
No, there is unfortunately no such thing as a SuiteExecutionListener in the Spring TestContext Framework (TCF).
The TCF does not integrate with JUnit 4 at the suite level.
If you want to store something in the TestContext, that's not a problem. TestContext implements org.springframework.core.AttributeAccessor, so you can store attributes in the TestContext. Note, however, that the lifecycle of a given TestContext is tied to a test class.
I'm trying to create a Junit test suite along with using PowerMockRunner but it does not work.
#RunWith(PowerMockRunner.class)
#PowerMockRunnerDelegate(MainTest.class)
#Suite.SuiteClasses({ MainTest.Class1Test.class })
#PrepareForTest({
StaticFieldsProvider.class
})
public class MainTest extends Suite {
public MainTest(Class<?> klass, RunnerBuilder builder)
throws InitializationError {
super(klass, builder);
}
public static class TestBase {
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
PowerMockito.mockStatic(StaticFieldsProvider.class);
}
}
public static class Class1Test extends TestBase {
#Before
public void setUp() {
super.setUp();
}
#Test
public void test(){
assertTrue(true);
}
}
}
When I try to run, it fails with error -
java.lang.IllegalArgumentException: Test class can only have one constructor
at org.junit.runners.model.TestClass.(TestClass.java:40)
Any suggestions on how to use PowerMockRunner in above case?
Thanks
This is an old question, so we may get no resolution on whether or not this solution works for the OP; but this might work (I can't verify without having access to StaticFieldsProvider, but it works if I swap that out with one of my own classes). I would love for someone to edit and add more explanation as to why this works:
#RunWith(PowerMockRunner.class)
// * Delegate to Suite.class instead of MainTest.class *
#PowerMockRunnerDelegate(Suite.class)
#Suite.SuiteClasses({ MainTest.Class1Test.class })
#PrepareForTest({
StaticFieldsProvider.class
})
// * Don't extend Suite *
public class MainTest {
// * Remove constructor *
public static class TestBase {
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
PowerMockito.mockStatic(StaticFieldsProvider.class);
}
}
public static class Class1Test extends TestBase {
#Before
public void setUp() {
super.setUp();
}
#Test
public void test(){
assertTrue(true);
}
}
}
In case it helps someone else, I had a slightly different scenario in that only a couple of the classes in my suite need PowerMockRunner (and don't mock out the same thing, so the mock needs to happen in each individual test class instead of in the runner). It appears that as long as I #PrepareForTest in my runner (as above) the classes I will need in some of the test classes, I can still create the mocks in the #Before (or wherever) of the applicable test class. Hope this helps.
You must not extend Suite, because this is a part of JUnit 3 and you are using JUnit 4. (Remove the extends and the constructor.) See the JUnit Wiki for more datails about Suites in JUnit 4.
I have a JUnit test suite in the form:
#RunWith(Suite.class)
#Suite.SuiteClasses( { xx.class, yy.cass })
public class AllTests {
public static Test suite() {
TestSuite suite = new TestSuite(AllTests.class.getName());
//$JUnit-BEGIN$
//$JUnit-END$
return suite;
}
}
This then calls vanilla tests like this:
public class xxx {
#Test
public void test () throws {
...
I have a situation where I'd like to stop the rest of the test suite running if there's an error or fail in the first test. But errors / fails in the others are ok and the suite should complete as many other tests as it can. Basically the first test failing would indicate it isn't safe to run the rest.
Is this possible?
First you need junit RunListener:
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;
import org.junit.runner.notification.RunNotifier;
public class FailureListener extends RunListener {
private RunNotifier runNotifier;
public FailureListener(RunNotifier runNotifier) {
super();
this.runNotifier=runNotifier;
}
#Override
public void testFailure(Failure failure) throws Exception {
super.testFailure(failure);
this.runNotifier.pleaseStop();
}
}
Then prepare a suite:
public class StopOnFailureSuite extends Suite {
public StopOnFailureSuite(Class<?> klass, Class<?>[] suiteClasses) throws InitializationError {
super(klass, suiteClasses);
}
public StopOnFailureSuite(Class<?> klass) throws InitializationError {
super(klass, klass.getAnnotation(SuiteClasses.class).value());
}
#Override
public void run(RunNotifier runNotifier) {
runNotifier.addListener(new FailureListener(runNotifier));
super.run(runNotifier);
}
}
And run your suite:
#RunWith(StopOnFailureSuite.class)
#Suite.SuiteClasses({
FirstTestClass.class,
SecondTestClass.class,
...
})
What's wrong with calling System.exit()?
If it's first test then consider moving its validation to #BeforeClass and throw exception if it fails. Then only #AfterClass method would run in case of this exception.
Of course, that way you lack all the fixture artifacts created in test setup method(s).
Like your answer but using #Before in an integration test, I did something like this:
public class FooTest {
private static boolean bar;
#BeforeClass
public static void setUpBeforeClass() throws Exception {
bar = false;
}
#Before
public void setUp() throws Exception {
assertTrue(bar);
}
#Test
public void test() {
System.out.println("something");
assertTrue(true);
}
#Test
public void test1() {
System.out.println("Something2");
assertTrue(true);
}
}
Regards!
Based on the answer from Hiro2k (thanks!) I've used the following solution. It's a bit of a hack but it works.
The test which can prevent other tests running goes at the top of the #Suite.SuiteClasses list. That test then has the following:
private static boolean shouldStopRestOfSuite = false;
#Test
public void test () throws Throwable {
try {
... run some test code...
}
catch (Throwable e) {
shouldStopRestOfSuite = true;
throw e;
}
}
Note the above does need to catch Throwable (not exception) so it catches assertion errors. It also re-throws the error so it's logged by JUnit for analysis.
Then there's another test method:
#Test
public void testKillIfNeeded () throws Exception {
if (!shouldStopRestOfSuite) {
return;
}
System.out.println ("Test suite killed due to dangerous error / failure");
System.exit(1);
}
The above is run second and will kill the JUnit process.
Using this method the JUnit test won't end on fail / error if there's an issue but the fail / error is logged for analysis by JUnit and no further tests will run.
Not too pretty but it does the job :)
Firstly you should catch an error and check the same before you run the 2nd test.
#Rule
public ErrorCollector collector = new ErrorCollector();
1. Add Error.
collector.addError(new Throwable("first thing went wrong"));
2. Check before the dependent run.
collector.checkThat(getResult(), not(containsString("ERROR!")));
Reference - ErrorCollector
Are you running tests using ant?
You could write a custom test listener. You can set this in ant http://ant.apache.org/manual/Tasks/junit.html ( enableTestListenerEvents).
I find it troubling that this functionality is so tedious to implement in such a mature library. If you're using JUnit 5 / Jupiter you can use an extension called JUnit Pioneer (https://junit-pioneer.org).
With JUnit Pioneer you can simply add a #DisableIfTestFails annotation to your test class to make all tests stop when one fails.