How do I use #RunWith with both JUnit4ClassRunner and JUnitParams? [duplicate] - java

I write unit test and want to use JUnitParamsRunner and MockitoJUnitRunner for one test class.
Unfortunately, the following does not work:
#RunWith(MockitoJUnitRunner.class)
#RunWith(JUnitParamsRunner.class)
public class DatabaseModelTest {
// some tests
}
Is there a way to use both, Mockito and JUnitParams in one test class?

You cannot do this because according to spec you cannot put the same annotation twice on the same annotated element.
So, what is the solution? The solution is to put only one #RunWith() with runner you cannot stand without and replace other one with something else. In your case I guess you will remove MockitoJUnitRunner and do programatically what it does.
In fact the only thing it does it runs:
MockitoAnnotations.initMocks(test);
in the beginning of test case. So, the simplest solution is to put this code into setUp() method:
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
I am not sure, but probably you should avoid multiple call of this method using flag:
private boolean mockInitialized = false;
#Before
public void setUp() {
if (!mockInitialized) {
MockitoAnnotations.initMocks(this);
mockInitialized = true;
}
}
However better, reusable solution may be implemented with JUnt's rules.
public class MockitoRule extends TestWatcher {
private boolean mockInitialized = false;
#Override
protected void starting(Description d) {
if (!mockInitialized) {
MockitoAnnotations.initMocks(this);
mockInitialized = true;
}
}
}
Now just add the following line to your test class:
#Rule public MockitoRule mockitoRule = MockitoJUnit.rule();
and you can run this test case with any runner you want.

As of JUnit 4.7 and Mockito 1.10.17, this functionality is built in; there is an org.mockito.junit.MockitoRule class. You can simply import it and add the line
#Rule public MockitoRule mockitoRule = MockitoJUnit.rule();
to your test class.

This solution works for every possible runner, not just this mockito example. For example; for Spring, just change the runner classes and add necessary annotations.
#RunWith(JUnitParamsRunner.class)
public class DatabaseModelTest {
#Test
public void subRunner() throws Exception {
JUnitCore.runClasses(TestMockitoJUnitRunner.class);
}
#RunWith(MockitoJUnitRunner.class)
public static class TestMockitoJUnitRunner {
}
}
DatabaseModelTest will be run by JUnit. TestMockitoJUnitRunner depends on it (by logic) and it will be run inside of the main in a #Test method, during the call JUnitCore.runClasses(TestMockitoJUnitRunner.class). This method ensures the main runner is started correctly before the static class TestMockitoJUnitRunner sub-runner runs, effectively implementing multiple nested #RunWith annotations with dependent test classes.
Also on https://bekce.github.io/junit-multiple-runwith-dependent-tests

Since the release of PowerMock 1.6, you can do it as easily as
#RunWith(PowerMockRunner.class)
#PowerMockRunnerDelegate(JUnitParamsRunner.class)
public class DatabaseModelTest {
// some tests
}
Explained here https://blog.jayway.com/2014/11/29/using-another-junit-runner-with-powermock/

In my case I was trying to Mock some method in spring bean and
MockitoAnnotations.initMocks(test);
doesn't works. Instead you have to define that bean to constructed using mock method inside your xml file like following.
...
<bean id="classWantedToBeMocked" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="com.fullpath.ClassWantedToBeMocked" />
</bean>
...
and add that bean with autowired inside your test class like following.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations="file:springconfig.xml")
public class TestClass {
...
#Autowired
private ClassWantedToBeMocked classWantedToBeMocked;
...
when(classWantedToBeMocked.methodWantedToBeMocked()).thenReturn(...);
...
}

check out this link https://bekce.github.io/junit-multiple-runwith-dependent-tests/
using this approach i combined a #RunWith(Parameterized.class) - outer runner - with #RunWith(MockitoJUnitRunner.class) - inner runner. The only tweak i had to add was to make my member variables in the outer class/runner static in order to make them accessible for the inner/nested runner/class. gook luck and enjoy.

I wanted to run SWTBotJunit4ClassRunner and org.junit.runners.Parameterized at the same time, I have parametric tests and I want to screenshots when the SWT test fails (the screenshot feature is provided by the SWTBotJunit4ClassRunner). #bekce's answer is great and first wanted go that route but it was either quirky passing through the arguments. Or doing the parametrized in the subclass and loosing the information what exact tests passed/failed and have only the last screenshot (as the screenshot names get the name from the test itself). So either way it was bit messy.
In my case the SWTBotJunit4ClassRunner is simple enough, so I cloned the source-code of the class, gave it my own name ParametrizedScreenshotRunner and where original was extending the TestRunner, my class is extending the Parameterized class so in essence I can use my own runner instead of the previous two. Boiled down my own runner extends on top of Parameterized runner while implementing the screenshot feature on top of it, now my test use this "hybrid" runner and all the tests work as expected straight away (no need to change anything inside the tests).
This is how it looks like (for sake of brevity I removed all the comments from the listing):
package mySwtTests;
import org.junit.runners.Parameterized;
import org.eclipse.swtbot.swt.finder.junit.ScreenshotCaptureListener;
import org.junit.runner.notification.RunListener;
import org.junit.runner.notification.RunNotifier;
public class ParametrizedScreenshotRunner extends TestRu Parameterized {
public ParametrizedScreenshotRunner(Class<?> klass) throws Throwable {
super(klass);
}
public void run(RunNotifier notifier) {
RunListener failureSpy = new ScreenshotCaptureListener();
notifier.removeListener(failureSpy); // remove existing listeners that could be added by suite or class runners
notifier.addListener(failureSpy);
try {
super.run(notifier);
} finally {
notifier.removeListener(failureSpy);
}
}
}

While there are no solution in JUnit 4 it is possible to register multiple extensions in JUnit 5:
#ExtendWith(MockitoExtension.class)
#ExtendWith(AnotherExtension.class)
public class MyTest {
// some tests
}
Note that JUnitParams framework is built into JUnit 5.

You can also try this:
#RunWith(JUnitParamsRunner.class)
public class AbstractTestClass {
// some tests
}
#RunWith(MockitoJUnitRunner.class)
public class DatabaseModelTest extends AbstractTestClass {
// some tests
}

Related

junit #RunWith(Parameterized.class) annotation is throwing null

I have a test which is extending to baseTest which is where I have included the parameters.
ATest.class
public class ATest extends BaseTest {
#Test
public void test() {
System.out.println(fSomething);
}
}
BaseTest.class
#RunWith(Parameterized.class)
public class BaseTest {
#Parameterized.Parameter
public Boolean fSomething;
#Parameterized.Parameters(name = "fSomething {0}")
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][] {{true}, {false}});
}
}
i am getting null value. If i set the constructor i am getting this error
org.junit.jupiter.api.extension.ParameterResolutionException: No ParameterResolver registered for parameter [boolean arg0] in constructor.
Can someone help me understand what is happening?
I notice you use Jupiter from jUnit 5, but jUnit 4 API.
If you use jUnit 5, reimplement the test using #ParametrizedTest annotation instead. Start here: https://junit.org/junit5/docs/current/user-guide/#writing-tests-parameterized-tests
If you want to stick with the jUnit 4 API for this particular test, replace the import for the #Test annotation: Instead of org.junit.jupiter.api.Test (jUnit 5) use org.junit.Test (jUnit 4).
For completeness, I recommend adding a constructor for the parameters in the base test class:
public BaseTest(Boolean fSomething) {
this.fSomething = fSomething;
}
... or use Lombok annotation #AllArgsConstructor or #RequiredArgsConstructor in case you make the field final (preferred).
In the code posted , i see #Test is being used in the derived class and using #parameterized in base class, as you are using both the annotation you see these issues. check the usage of it.

Testing one Spring Test Class for many different set of profiles

I am working with:
Spring Framework 4.3.10
JUnit 4.12
Gradle 4.3.1
I have these two test classes
#Transactional
#RunWith(Parameterized.class)
#ContextConfiguration(classes={RootApplicationContext.class})
#ActiveProfiles(resolver=TestJdbcActiveProfilesResolver.class)
#TestExecutionListeners(listeners={LoggingTestExecutionListener.class}, mergeMode=MergeMode.MERGE_WITH_DEFAULTS)
public class PersonaServiceImplJdbcTest {
#Transactional
#RunWith(Parameterized.class)
#ContextConfiguration(classes={RootApplicationContext.class})
#ActiveProfiles(resolver=TestHibernateActiveProfilesResolver.class)
#TestExecutionListeners(listeners={LoggingTestExecutionListener.class}, mergeMode=MergeMode.MERGE_WITH_DEFAULTS)
public class PersonaServiceImplHibernateTest {
The code about the #Test methods are the same for both Test classes, breaking the DRY principle, the unique difference between these two test classes is the jdbc and Hibernate profiles working together with other such as development, mysql, it internally through each TestXXXActiveProfilesResolver class variation.
Until here I have 2 test classes, breaking the DRY principle, thinking in hierarchy I am going to get 3.
How (if is possible) use one Test class where for each interaction executes two (or more) sets of profiles such as:
jdbc,development,mysql
Hibernate,development,mysql
I already have read:
Spring Boot / JUnit, run all unit-tests for multiple profiles
But I want avoid use commands either through Maven or Gradle, it to keep the control through the TestXXXActiveProfilesResolver classes.
For JUnit 4 finally I did the following (scroll down):
#Transactional
#RunWith(Parameterized.class)
#ContextConfiguration(classes={RootApplicationContext.class})
//#ActiveProfiles() ... disable
#TestExecutionListeners(listeners={LoggingTestExecutionListener.class}, mergeMode=MergeMode.MERGE_WITH_DEFAULTS)
public abstract class PersonaServiceImplTest {
...
#Autowired
private Environment environment;
#Before
public void setup(){
logger.info("Profiles: {}", Arrays.toString(environment.getActiveProfiles()));
}
//#Test disable
public void someTest(){
assertThat(...)
}
#ActiveProfiles(resolver=TestJdbcActiveProfilesResolver.class)
public static class ForJdbc extends PersonaServiceImplTest {
public ForJdbc(Persona persona){
super(persona);
}
#Test
#Override
#Sql(scripts={"classpath:/.../script.sql"})//when be necessary
public void someTest()(){
super.someTest()();
}
}
#ActiveProfiles(resolver=TestHibernateActiveProfilesResolver.class)
public static class ForHibernate extends PersonaServiceImplTest {
public ForHibernate(Persona persona){
super(persona);
}
#Test
#Override
#Sql(scripts={"classpath:/.../script.sql"})//when be necessary
public void someTest()(){
super.someTest()();
}
...
}
}
Observations:
The outer class must be abstract
The outer class must have no #ActiveProfiles declared
The outer class has the methods to be tested, each one must have no the #Test declared
Environment is optional but is useful to let know the profiles activated for each static nested class, it through the common method annotated with #Before
Each static nested class must be public
Each static nested class must extends the outer class
Each static nested class must have #ActiveProfiles
Each static nested class overrides each test method, just to use super to call the respective overridden method
Each static nested class, for each test overridden method, it must have the #Test.
#Sql can't be reused, it must be declared for each overridden method

Make ApplicationContext dirty before and after test class

I have a particular class (let's say MyTest) in my Spring integration tests that is using PowerMock #PrepareForTest annotation on a Spring component: #PrepareForTest(MyComponent.class). This means that PowerMock will load this class with some modifications. The problem is, my #ContextConfiguration is defined on the superclass which is extended by MyTest, and the ApplicationContext is cached between different test classes. Now, if MyTest is run first, it will have the correct PowerMock version of MyComponent, but if not - the test will fail since the context will be loaded for another test (without #PrepareForTest).
So what I want to do is to reload my context before MyTest. I can do that via
#DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
But what if I also want to reload context after this test is done? So I will have clean MyComponent again without PowerMock modifications. Is there a way to do both BEFORE_CLASS and AFTER_CLASS?
For now I did it with the following hack:
#FixMethodOrder(MethodSorters.NAME_ASCENDING)
on MyTest and then
/**
* Stub test to reload ApplicationContext before execution of real test methods of this class.
*/
#DirtiesContext(methodMode = DirtiesContext.MethodMode.BEFORE_METHOD)
#Test
public void aa() {
}
/**
* Stub test to reload ApplicationContext after execution of real test methods of this class.
*/
#DirtiesContext(methodMode = DirtiesContext.MethodMode.AFTER_METHOD)
#Test
public void zz() {
}
I am wondering if there is a prettier way to do that?
As a side question, is it possible to reload only certain bean and not full context?
Is there a way to do both BEFORE_CLASS and AFTER_CLASS?
No, that is unfortunately not supported via #DirtiesContext.
However, what you're really saying is that you want a new ApplicationContext for MyTest that is identical to the context for the parent test class but only lives as long as MyTest. And... you don't want to affect the context cached for the parent test class.
So with that in mind, the following trick should do the job.
#RunWith(SpringJUnit4ClassRunner.class)
// Inherit config from parent and combine with local
// static Config class to create a new context
#ContextConfiguration
#DirtiesContext
public class MyTest extends BaseTests {
#Configuration
static class Config {
// No need to define any actual #Bean methods.
// We only need to add an additional #Configuration
// class so that we get a new ApplicationContext.
}
}
Alternative to #DirtiesContext
If you want to have a context dirtied both before and after a test class, you can implement a custom TestExecutionListener that does exactly that. For example, the following will do the trick.
import org.springframework.core.Ordered;
import org.springframework.test.annotation.DirtiesContext.HierarchyMode;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.support.AbstractTestExecutionListener;
public class DirtyContextBeforeAndAfterClassTestExecutionListener
extends AbstractTestExecutionListener {
#Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
#Override
public void beforeTestClass(TestContext testContext) throws Exception {
testContext.markApplicationContextDirty(HierarchyMode.EXHAUSTIVE);
}
#Override
public void afterTestClass(TestContext testContext) throws Exception {
testContext.markApplicationContextDirty(HierarchyMode.EXHAUSTIVE);
}
}
You can then use the custom listener in MyTest as follows.
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.TestExecutionListeners.MergeMode;
#TestExecutionListeners(
listeners = DirtyContextBeforeAndAfterClassTestExecutionListener.class,
mergeMode = MergeMode.MERGE_WITH_DEFAULTS
)
public class MyTest extends BaseTest { /* ... */ }
As a side question, is it possible to reload only certain bean and not full context?
No, that is also not possible.
Regards,
Sam (author of the Spring TestContext Framework)

Multiple RunWith Statements in jUnit

I write unit test and want to use JUnitParamsRunner and MockitoJUnitRunner for one test class.
Unfortunately, the following does not work:
#RunWith(MockitoJUnitRunner.class)
#RunWith(JUnitParamsRunner.class)
public class DatabaseModelTest {
// some tests
}
Is there a way to use both, Mockito and JUnitParams in one test class?
You cannot do this because according to spec you cannot put the same annotation twice on the same annotated element.
So, what is the solution? The solution is to put only one #RunWith() with runner you cannot stand without and replace other one with something else. In your case I guess you will remove MockitoJUnitRunner and do programatically what it does.
In fact the only thing it does it runs:
MockitoAnnotations.initMocks(test);
in the beginning of test case. So, the simplest solution is to put this code into setUp() method:
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
I am not sure, but probably you should avoid multiple call of this method using flag:
private boolean mockInitialized = false;
#Before
public void setUp() {
if (!mockInitialized) {
MockitoAnnotations.initMocks(this);
mockInitialized = true;
}
}
However better, reusable solution may be implemented with JUnt's rules.
public class MockitoRule extends TestWatcher {
private boolean mockInitialized = false;
#Override
protected void starting(Description d) {
if (!mockInitialized) {
MockitoAnnotations.initMocks(this);
mockInitialized = true;
}
}
}
Now just add the following line to your test class:
#Rule public MockitoRule mockitoRule = MockitoJUnit.rule();
and you can run this test case with any runner you want.
As of JUnit 4.7 and Mockito 1.10.17, this functionality is built in; there is an org.mockito.junit.MockitoRule class. You can simply import it and add the line
#Rule public MockitoRule mockitoRule = MockitoJUnit.rule();
to your test class.
This solution works for every possible runner, not just this mockito example. For example; for Spring, just change the runner classes and add necessary annotations.
#RunWith(JUnitParamsRunner.class)
public class DatabaseModelTest {
#Test
public void subRunner() throws Exception {
JUnitCore.runClasses(TestMockitoJUnitRunner.class);
}
#RunWith(MockitoJUnitRunner.class)
public static class TestMockitoJUnitRunner {
}
}
DatabaseModelTest will be run by JUnit. TestMockitoJUnitRunner depends on it (by logic) and it will be run inside of the main in a #Test method, during the call JUnitCore.runClasses(TestMockitoJUnitRunner.class). This method ensures the main runner is started correctly before the static class TestMockitoJUnitRunner sub-runner runs, effectively implementing multiple nested #RunWith annotations with dependent test classes.
Also on https://bekce.github.io/junit-multiple-runwith-dependent-tests
Since the release of PowerMock 1.6, you can do it as easily as
#RunWith(PowerMockRunner.class)
#PowerMockRunnerDelegate(JUnitParamsRunner.class)
public class DatabaseModelTest {
// some tests
}
Explained here https://blog.jayway.com/2014/11/29/using-another-junit-runner-with-powermock/
In my case I was trying to Mock some method in spring bean and
MockitoAnnotations.initMocks(test);
doesn't works. Instead you have to define that bean to constructed using mock method inside your xml file like following.
...
<bean id="classWantedToBeMocked" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="com.fullpath.ClassWantedToBeMocked" />
</bean>
...
and add that bean with autowired inside your test class like following.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations="file:springconfig.xml")
public class TestClass {
...
#Autowired
private ClassWantedToBeMocked classWantedToBeMocked;
...
when(classWantedToBeMocked.methodWantedToBeMocked()).thenReturn(...);
...
}
check out this link https://bekce.github.io/junit-multiple-runwith-dependent-tests/
using this approach i combined a #RunWith(Parameterized.class) - outer runner - with #RunWith(MockitoJUnitRunner.class) - inner runner. The only tweak i had to add was to make my member variables in the outer class/runner static in order to make them accessible for the inner/nested runner/class. gook luck and enjoy.
I wanted to run SWTBotJunit4ClassRunner and org.junit.runners.Parameterized at the same time, I have parametric tests and I want to screenshots when the SWT test fails (the screenshot feature is provided by the SWTBotJunit4ClassRunner). #bekce's answer is great and first wanted go that route but it was either quirky passing through the arguments. Or doing the parametrized in the subclass and loosing the information what exact tests passed/failed and have only the last screenshot (as the screenshot names get the name from the test itself). So either way it was bit messy.
In my case the SWTBotJunit4ClassRunner is simple enough, so I cloned the source-code of the class, gave it my own name ParametrizedScreenshotRunner and where original was extending the TestRunner, my class is extending the Parameterized class so in essence I can use my own runner instead of the previous two. Boiled down my own runner extends on top of Parameterized runner while implementing the screenshot feature on top of it, now my test use this "hybrid" runner and all the tests work as expected straight away (no need to change anything inside the tests).
This is how it looks like (for sake of brevity I removed all the comments from the listing):
package mySwtTests;
import org.junit.runners.Parameterized;
import org.eclipse.swtbot.swt.finder.junit.ScreenshotCaptureListener;
import org.junit.runner.notification.RunListener;
import org.junit.runner.notification.RunNotifier;
public class ParametrizedScreenshotRunner extends TestRu Parameterized {
public ParametrizedScreenshotRunner(Class<?> klass) throws Throwable {
super(klass);
}
public void run(RunNotifier notifier) {
RunListener failureSpy = new ScreenshotCaptureListener();
notifier.removeListener(failureSpy); // remove existing listeners that could be added by suite or class runners
notifier.addListener(failureSpy);
try {
super.run(notifier);
} finally {
notifier.removeListener(failureSpy);
}
}
}
While there are no solution in JUnit 4 it is possible to register multiple extensions in JUnit 5:
#ExtendWith(MockitoExtension.class)
#ExtendWith(AnotherExtension.class)
public class MyTest {
// some tests
}
Note that JUnitParams framework is built into JUnit 5.
You can also try this:
#RunWith(JUnitParamsRunner.class)
public class AbstractTestClass {
// some tests
}
#RunWith(MockitoJUnitRunner.class)
public class DatabaseModelTest extends AbstractTestClass {
// some tests
}

Junit - run set up method once

I set up a class with a couple of tests and rather than using #Before I would like to have a setup method that executes only once before all tests. Is that possible with Junit 4.8?
Although I agree with #assylias that using #BeforeClass is a classic solution it is not always convenient. The method annotated with #BeforeClass must be static. It is very inconvenient for some tests that need instance of test case. For example Spring based tests that use #Autowired to work with services defined in spring context.
In this case I personally use regular setUp() method annotated with #Before annotation and manage my custom static(!) boolean flag:
private static boolean setUpIsDone = false;
.....
#Before
public void setUp() {
if (setUpIsDone) {
return;
}
// do the setup
setUpIsDone = true;
}
You can use the BeforeClass annotation:
#BeforeClass
public static void setUpClass() {
//executed only once, before the first test
}
JUnit 5 now has a #BeforeAll annotation:
Denotes that the annotated method should be executed before all #Test
methods in the current class or class hierarchy; analogous to JUnit
4’s #BeforeClass. Such methods must be static.
The lifecycle annotations of JUnit 5 seem to have finally gotten it right! You can guess which annotations available without even looking (e.g. #BeforeEach #AfterAll)
When setUp() is in a superclass of the test class (e.g. AbstractTestBase below), the accepted answer can be modified as follows:
public abstract class AbstractTestBase {
private static Class<? extends AbstractTestBase> testClass;
.....
public void setUp() {
if (this.getClass().equals(testClass)) {
return;
}
// do the setup - once per concrete test class
.....
testClass = this.getClass();
}
}
This should work for a single non-static setUp() method but I'm unable to produce an equivalent for tearDown() without straying into a world of complex reflection... Bounty points to anyone who can!
JUnit 5 #BeforeAll can be non static provided the lifecycle of the test class is per class, i.e., annotate the test class with a #TestInstance(Lifecycle.PER_CLASS) and you are good to go
Edit:
I just found out while debugging that the class is instantiated before every test too.
I guess the #BeforeClass annotation is the best here.
You can set up on the constructor too, the test class is a class after all.
I'm not sure if it's a bad practice because almost all other methods are annotated, but it works. You could create a constructor like that:
public UT () {
// initialize once here
}
#Test
// Some test here...
The ctor will be called before the tests because they are not static.
Use Spring's #PostConstruct method to do all initialization work and this method runs before any of the #Test is executed
Try this solution:
https://stackoverflow.com/a/46274919/907576 :
with #BeforeAllMethods/#AfterAllMethods annotation you could execute any method in Test class in an instance context, where all injected values are available.
My dirty solution is:
public class TestCaseExtended extends TestCase {
private boolean isInitialized = false;
private int serId;
#Override
public void setUp() throws Exception {
super.setUp();
if(!isInitialized) {
loadSaveNewSerId();
emptyTestResultsDirectory();
isInitialized = true;
}
}
...
}
I use it as a base base to all my testCases.
If you don't want to force a declaration of a variable that is set and checked on each subtest, then adding this to a SuperTest could do:
public abstract class SuperTest {
private static final ConcurrentHashMap<Class, Boolean> INITIALIZED = new ConcurrentHashMap<>();
protected final boolean initialized() {
final boolean[] absent = {false};
INITIALIZED.computeIfAbsent(this.getClass(), (klass)-> {
return absent[0] = true;
});
return !absent[0];
}
}
public class SubTest extends SuperTest {
#Before
public void before() {
if ( super.initialized() ) return;
... magic ...
}
}
I solved this problem like this:
Add to your Base abstract class (I mean abstract class where you initialize your driver in setUpDriver() method) this part of code:
private static boolean started = false;
static{
if (!started) {
started = true;
try {
setUpDriver(); //method where you initialize your driver
} catch (MalformedURLException e) {
}
}
}
And now, if your test classes will extends from Base abstract class -> setUpDriver() method will be executed before first #Test only ONE time per run.
Here is one alternative suggestion:
What I do to get this working is
Create a method named _warmup or just _
Annotate the test class with #FixMethodOrder(MethodSorters.NAME_ASCENDING)
This is applicable only if you run all tests in the class
It has a downside of having additional test included, which will also run one additional #Before and #After
It is usually advised for your test methods to be order independent, this breaks that rule, but why someone would like tests ordered randomly in the reports I have no clue so NAME_ASCENDING is what I always use
But the upsides to this is simple setup with minimal code and without the need to extend classes/runners etc...
Test run lengths are more accurate since all setup time is reported on method _warmup
After experimenting for some time this is my solution. I needed this for spring boot test. I tried using #PostConstruct, unfortunately it is executed for every test.
public class TestClass {
private static TestClass testClass = null;
#Before
public void setUp() {
if (testClass == null) {
// set up once
...
testClass = this;
}
}
#AfterClass
public static void cleanUpAfterAll() {
testClass.cleanUpAfterAllTests();
}
private void cleanUpAfterAllTests() {
// final cleanup after all tests
...
}
#Test
public void test1() {
// test 1
...
}
#Test
public void test2() {
// test 2
...
}
}
The problem with #BeforeClass is that it fires before the constructor.
So if you rely on an #Autowired constructor to provide data, it simply will not work: wrong execution order.
Similarly #PostConstruct fires after the constructor has been called. And the constructor fires with every #Test, therefore your setup function will fire with every test, if you use this.
This has the exact same effect as calling a function from the constructor.
The only solution, I found that works, is to use a flag to indicate if the setUp() method has already been executed. While its not ideal, it will drastically reduce the amount of processing before each test.
private static boolean initialized = false;
#Autowired
public CacheTest( MyBean myBean ){
this.myBean = myBean;
}
#PostConstruct
public static void setUp(){
if( initialized ) { return };
initialized = true;
//do suff with myBean
}

Categories