In a project there are multiple test classes each containing multiple test methods. Say, I want to create a database connection before running each of these test classes. The connection should be made regardless of whether I run an individual test class, multiple test classes or a test suite.
Most importantly this step should not be called over and over again in case of multiple test classes. The connection should be made only once regardless of number of test classes I'm running.
Could you suggest a design or any JUnit tips to tackle this issue ?
You could run the classes in a test suite. Refer this question and the answers provided.
Or change your design and use #BeforeClass annotation to run setup once before each test class.
Sometimes several tests need to share computationally expensive setup
(like logging into a database). While this can compromise the
independence of tests, sometimes it is a necessary optimization.
Annotating a public static void no-arg method with #BeforeClass causes
it to be run once before any of the test methods in the class. The
#BeforeClass methods of superclasses will be run before those the
current class.
Use #Before Junit annotation
When writing tests, it is common to find that several tests need
similar objects created before they can run. Annotating a public void
method with #Before causes that method to be run before the Test
method. The #Before methods of superclasses will be run before those
of the current class.
Simply introduce a superclass for all your junit classes. You can put the database connection logic in your Superclass #Before annotated method.
If you're using spring-test, then you could use the technique employed here: How to load DBUnit test data once per case with Spring Test
Related
I am creating Unit Tests in Java and for each method, I create the same lists, variables, etc. On the other hand, of course I thought that I could create all of these variables as global and set their values in the setup() method (in #Before), but I am not sure if the values may be changed when running tests due to multithreading, etc. So, what is the best way for this situation?
Nothing to worry about. JUnit will create a new instance of your test class, and then run each #Before method, and only then run the #Test method, and it does that song and dance routine all over again for every #Test annotated method in that class. You're using #Before exactly as it was intended: It's for storing initialization code that is required for all the tests in that test class.
JUnit does it this way because 'test independence' is nice to have: Tests, preferably, fail or pass independent of the ordering in which you execute them.
Every so often the init process is so expensive that it's not worth it to pay the 'cost' of running it over and over again for every test. The annotation #BeforeClass exists specifically for that purpose. The javadoc of #BeforeClass even spells out that this compromises test independence and should therefore only be used if the setup work you do within such a method is sufficiently expensive (computationally or otherwise) to make that tradeoff.
In other words:
Your worries about test independence are real, but they apply to #BeforeClass. #Before doesn't suffer from this problem; that code is re-run for every test.
NB: You can toss all this out the window if you have static stuff going on. Don't have static stuff in test code unless you really know what you're doing. I assume you don't have that in which case - carry on, your tests are independent.
For optimizing purpose I need to customize TestExecutionListeners invoking logic
In my case I have one ApplicationContext and two types of tests:
Ones which use WebDriver (let’s call it ObservableTest)
Ones which use RestTemplate and JdbcTemplate (let’s call it ApiTest)
Each type uses its own TestExecutionListener:
ObservableTest - ObservableTestListener
ApiTest - ApiTestListener
Both ObservableTestListener and ApiTestListener extend TestListener where prepareTestInstance() is defined
ObservableTestListener implements beforeTestClass() and afterTestClass() methods as well as ApiTestListener does
I need combine test types above in one JUnit TestSuite in the next way:
For each test prepareTestInstance() is invoked
As soon as first ObservableTest is about to be instantiated, beforeTestClass() of ObservableTestListener is executed
The same with ApiTest
afterTestClass() of ObservableTestListener is invoked when last ObservableTest is finished in current Suite
The same with ApiTest
Things got even more complicated as each test may be run in one suite and in different ApplicationContexts (due to different profiles usage)
I would be very grateful for any hint and digging direction to implement such logic properly
I have two ideas so far:
Implementing custom Runner (I'm not confident it is even possible)
Notify TestContextManager somehow that particular method (beforeTestClass() or afterTestClass()) should or should not be invoked. I have a feeling that #BootstrapWith custom SpringClassRule should help me in that
Thanks!
The TestExecutionListener API in the Spring TestContext Framework does not have any lifecycle callbacks at the suite level.
Thus, out of the box, there is no way to instruct Spring to invoke methods on TELs before or after a suite. Consequently, any solution you come up with to support your requirements will have to be completely custom.
I don't foresee how a custom SpringClassRule would be that useful: you will still need some reliable mechanism for determining when a test suite begins and ends. That is actually the biggest challenge since suite support in JUnit 4 is via a specific Runner. So, if you run all of your tests via a JUnit 4 Suite, you could potentially build in your own lifecycle callbacks in a custom subclass of Suite.
Regards,
Sam (author of the Spring TestContext Framework)
I was wondering about this question by having some trouble writting unit tests for my spring application.
Let's take the following example:
#SpringBootTest
#RunWith(SpringRunner.class)
public class AlbumDTOConverterTest {
#Autowired
private AlbumDTOConverter albumDTOConverter;
#Test
public void ToEntity_ReturnValue_NotNull() {
AlbumDTO albumDTO = new AlbumDTO("Summer album", new Date(), "This summer, we have made some wonderfull photos. Have a look!", null);
assertNotNull(albumDTOConverter.toEntity(albumDTO));
}
}
In order to make #Autowired work properly, I am launching a container with annotating the test class with #SpringBootTest.
The thing is that I think I am doing this wrong. In my opinion, I'll rather just create a new instance of AlbumDTOConverter by just using the new operator instead of using Spring's IoD.
What do you guys think about this ?
For unit tests you don't need a whole container to start. By definition, such units should be tested in isolation. Creating an instance of a class with the new keyword is perfectly fine. Even if the class has dependencies on other classes, you can also create them manually and pass to an appropriate constructor of the class.
Note that the unit is not the same as the class. The term of the unit is commonly confused among developers, especially beginners. You don't have to rely on the dependency injection in your unit tests. The container will only increase the time needed to execute the tests and the long execution time is the main reason why developers avoid running them very often. There is nothing wrong in manually building your dependency tree for a unit under tests.
In the long run, creating similar inputs for different tests might lead to duplication in the test code, but fortunately there are best practices for this problem, e.g. shared fixture.
If you are doing unit test then you should not use #Autowire every time.
Unit test basic says "Unit tests are responsible for testing a specific piece of code, just a small functionality (unit) of the code"
Now question is when to use spring capabilities ?
Sometimes, you'll need to do some unit tests relying on Spring framework like web service call, repository call etc. For example, if you have a repository that has a custom query using the #Query annotation, you might need to test your query. Also, if you are serialising/deserialising objects, you'd want to make sure that your object mapping is working. You might want to test your controllers as well, when you have some parameter validation or error handling. How can you be sure that you are using Spring correctly? In these situations you can take advantage of the new Spring Boot's test annotations.
I thinks this will give better idea.
This question already has answers here:
Difference between #Before, #BeforeClass, #BeforeEach and #BeforeAll
(7 answers)
Closed 4 years ago.
According to this answer, the #Before annotation is executed once before each test, whereas the #BeforeClass annotation is only executed once before all tests.
My intuition tells me to always use #BeforeClass, so the question is, why even use #Before? Is there a case where the #Before annotation performs better/faster than the #BeforeClass annotation?
Each test should be isolated. By using BeforeClass then the state of the previous test could be hanging about and messing up the later tests.
One generally uses BeforeClass to setup an expensive external resource and Before to reset the world (be that the external resource or local).
One final note:
performs better/faster
In this case I would say the two properties should be treated independently here (that is better!=faster). As long as the total time to run your complete tests suite is under 10 minutes then "faster" is simply not important.
Once you go above that magic ten minutes (and at this point you will definitely be talking integration tests not unit tests) then start looking for ways to make things "faster".
I'll give you an example:
Say you need to validate a form in your web application. You are going to use Selenium for that.
Your test class will have 10 tests. You don't need to open and close your webdriver browser each time you start your test suite. In such case, you iniatilize your webdrive browser on a #BeforeClass method.
However, for each validation test you need to reset your form. This action you will perform on a #Before method.
This is a very simple example, but may make things clearer.
When you use #BeforeClass it suggests that you do initialization before all the tests. So one test might depend on other one (e.g. if tests change the state of fields), so I would encourage usage of #Before, or even better to do preparations for the test method inside the method itself.
There are very rarely cases when your tests need exactly the same initial state, so why couple them together?
We are following below practices to write JUnit tests for our methods.
Each method will be having their own class which holds all the tests which are required for that method. For e.g.: class test {...}
#Before will consists of per-requisites setup for methods like "Entity" so that when we do Edit we don't need to copy/paste code for adding an entity at each method level.
Now here my question is, shall we delete all the data which we entered by writing code to trash test-data in #after method or just let it be?
I know we can make it configurable but what is best practice? keep it or delete it. As per my gut feeling deleting should be better as if there is some duplicate data already in db - it may trigger wrong true or false.
It depends on how much you adhere to the Don't Repeat Yourself principle. It's also worth remembering that you have #After called after each #Test and #AfterClass called after all the #Test have run. With this granularity, it should be simple to remove duplication but still split those tasks that should only run at the very end, or after each test.
As a best practice I would recommend to clear your data storage between every test, to guarantee each test is isolated from other tests.
This could be done with the #After method if you want to keep some of the settings alive (from the #BeforeClassfor example). It could also be done in the #Before method for example by overriding variables with a new instance for every test, if you do so you do not need a clean up after the tests.
To clean up your settings of the #BeforeClass method you should use #AfterClass for example to close a Database connection or something simular what only needed to be done once. But this is not needed for every kind of unit test.