How do you clear objects between JUnit/Maven tests? - java

I'm testing different parts of a miniature search engine, and some of the JUnit tests are leaving entries in the index that interfere with other tests. Is there a convention in JUnit/Maven for clearing objects between tests?

There are 2 particular annotations that can help you with this, and are intended to be used in cases such as yours:
#After defines that a certain method must be executed after every #Test, while #AfterClass is the method to execute once the entire test class has been executed. Think of the latter as a last cleanup method to purge any structures or records you've been using and sharing between tests so far.
Here is an example:
#After
public void cleanIndex() {
index.clear(); //Assuming you have a collection
}
#AfterClass
public void finalCleanup() {
//Clean both the index and, for example, a database record.
}
Note: They have their counterparts (#Before and #BeforeClass) that to exactly the opposite by invoking the related methods before a #Test method and before starting to execute the #Tests defined on that class. This ones are the setUp used in previous versions of JUnit.
If you can't use annotations, the alternative is to use the good old tearDown method:
public void tearDown() {
index.clear(); //Assuming you have a collection.
}
This is provided by the JUnit framework and behaves like a method annotated with #After.

You should make use of the #Before annotation to guarantee that each test is running from a clean state. Please see: Test Fixtures.

Inside of your junit testing class, you can override the methods setup and teardown. setup will run before every one of your tests while teardown will run after every single junit test that you have.
ex:
public class JunitTest1 {
private Collection collection;
//Will initialize the collection for every test you run
#Before
public void setUp() {
collection = new ArrayList();
System.out.println("#Before - setUp");
}
//Will clean up the collection for every test you run
#After
public void tearDown() {
collection.clear();
System.out.println("#After - tearDown");
}
//Your tests go here
}
This is useful for clearing out data inbetween tests, but also allows you to not have to reinitialize your fields inside of every single test.

Related

invoking a test method each time before other test methods

I have a test method as below that two other test methods are dependent to this method and this method should run before these two each time and not only once for both.
#Test(dataProvider = "requestParameterProvider", groups = "jsonRequest")
public void saveNewActivity_correctValues(Service service,
Map<String, Object> requestMap){}
#Test(dependsOnMethods = "saveNewActivity_trackRequest_correctValues", dataProvider = "responseParameterProvider")
public void commitActivity_correctValues(Service service){}
#Test(dependsOnMethods = "saveNewActivity_trackRequest_correctValues", dataProvider = "exceptionParameterProvider")
public void failActivity_correctValues(Service service, FailureReason failureReason){}
what happens at above case is saveNewActivity_correctValues method run once first and then two other method run after that. but i want first method to be invoked two times before each dependent method and once as separate test. i can't put first method as #BeforeMethod because it is already a test and have a provider of it's own.
Use the #Before annotation on the method you want to run before all tests.
If you don't want it to run before all methods, but only some, either refactor your tests out into 2 classes and use #Before in one, and not in the other and move your methods appropriately.
The other option is to just call the method(s) from each test you want them to run before.
I'm assuming you are using JUnit - so see here:
http://junit.sourceforge.net/javadoc/org/junit/Before.html
If not, update your post with what you are using.

How and when to cleanup using Mockito Annotations with jUnit

I'm currently having some memory problems with some unit tests in a fairly large project of mine. Throughout my hair pulling and research today, I have come to realize that it appears to be related to objects not always being cleaned up as fast as I think they should be cleaned up. I started researching "cleanup mockito" and "cleanup junit" and came across a few blogs and forum posts about how to use #Before and #After (as well as their *Class versions) to do intense things that you don't want being done with every unit test. This got me to thinking about Mockito's #Mock and #InjectMocks annotations.
Can someone please describe to me in detail how the class variables below are being handled in memory during a maven build? Will the objects be created before, during, or after unit tests? Are the objects immediately destroyed after the last unit tests completes? Should I be using #After to set all the class variables to null?
Thanks many times over. Here's a sample of a test case I may use:
#RunWith(MockitoJUnitRunner.class)
public class thisCustomTest {
#Mock
MyCustomSpringBean myCustomerSpringBean;
#InjectMocks
MyBeanToTest myBeanToTest;
#Before
public void config() {
MockitoAnnotations.initMocks(this);
}
#Test
public void someTest() {
//code here
}
}
Just to do a quick wrap-up / summary at the end, my main question is whether or not I should be utilizing something like #After to clean up class variables, or should I simply leave those for Java's normal scope garbage collection...
My idea of cleanup:
#After
public void cleanup() {
mockedClassVariable = null;
injectedVariable = null;
}
JUnit creates a new instance of your unit test class before running each test method. Once the instance is created, its #Before annotated method(s) is (are) executed. Then the test method is executed. Then, whatever happened in the test method (success, failure or error), the #After annotated method(s) is (are) run.
So, in this particular case, MockitoAnnotations.initMocks(this) is executed before each test method, which creates a new mock each time, a new MyBeanToTest each time, and injects the mock into the bean to test.
Those beans will be eligible for GC, along with the test instance which references them, after the test method execution. Setting them to null in the cleanup method doesn't serve any purpose.

How can I make JUnit 4.8 run code after a failed test, but before any #After methods?

I'm driving a suite of Selenium tests (actually WebDriver-backed Selenium) using JUnit 4.8.2. I'd like the tests to automatically take a screenshot of the browser as soon as the test fails an assertion. All the tests inherit from SeleniumBaseTestCase, and the majority then further inherit from from SeleniumBastTestCaseWithCompany (which uses #Before and #After methods to create and then clean up common test data via Selenium).
I've tried adding a subclass of TestWatchman as a #Rule in SeleniumBaseTestCase, overriding TestWatchman's failed method to take the screenshot. The trouble is that the #After methods cleaning up the test data are being run before TestWatchman's failed method is called, so the screenshots are all of the final step of the clean-up, not the test that failed.
Looking into it a little, it seems that TestWatchman's apply method just calls the passed Statement's evaluate method (the only exposed method), which calls the #After methods, leaving TestWatchman (or any other Rule) no chance to insert any code between the execution of the test and of the #After methods, as far as I can tell.
I've also seen approaches that create a custom Runner to alter the Statements created so that methods annotated with the custom #AfterFailure are run before #After methods (so the screenshot can be taken in such an #AfterFailure method), but this relies on overriding BlockJUnit4ClassRunner's withAfters method, which is deprecated and due to become private, according to the documentation, which suggests using Rules instead.
I've found another answer on SO about the #Rule lifecycle that makes it sound like this simply might not be possible in JUnit 4.8, but may be possible in JUnit 4.10. If that's correct then fair enough, I'd just like confirmation of that first.
Any thoughts on an elegant and future-proof way in which I can achieve what I want would be much appreciated!
You are right in your analysis, #Befores and #Afters are added to the list of Statements before any Rules. The #Before gets executed after the #Rule and the #After gets executed before the #Rule. How you fix this depends on how flexible you can be with SeleniumBaseTestCaseWithCompany.
The easiest way would be to remove your #Before/#After methods and replace them with an ExternalResource. This could look something like:
public class BeforeAfterTest {
#Rule public TestRule rule = new ExternalResource() {
protected void before() throws Throwable { System.out.println("externalResource before"); }
protected void after() { System.out.println("externalResource after"); }
};
#Test public void testHere() { System.out.println("testHere"); }
}
this gives:
externalResource before
testHere
externalResource after
This field can be put into your base class, so it gets inherited/overridden. Your problem with ordering between #After and your rules then goes away, because you can order your rules how you like, using #RuleChain (in 4.10, not 4.8).
If you can't change SeleniumBaseTestCaseWithCompany, then you can extend BlockJUnit4ClassRunner, but don't override withAfters, but override BlockJUnit4ClassRunner#methodBlock(). You can then call super.methodBlock, and reorder the Statements as necessary[*].
[*]You could just copy the code, and reorder the lines, but withRules is private and therefore not callable from a subclass.

mockito : how to unmock a method?

I have a JUnit class with different methods to perform different tests.
I use Mockito to create a spy on real instance, and then override some method which is not relevant to the actual test I perform.
Is there a way, just for the sake of cleaning up after me in case some other tests that run after my tests also use the same instances and might execute a mocked method they didn't ask to mock, to un-mock a method?
say I have a spy object called 'wareHouseSpy'
say I overriden the method isSomethingMissing :
doReturn(false).when(wareHouseSpy).isSomethingMissing()
What will be the right way to un-override, and bring things back to normal on the spy i.e make the next invokation of isSomethingMissing to run the real method?
something like
doReturn(Mockito.RETURN_REAL_METHOD).when(wareHouseSpy).isSomethingSpy()
or maybe
Mockito.unmock(wareHouseSpy)
Who knows? I couldn't find nothing in that area
Thanks!
Assaf
I think
Mockito.reset(wareHouseSpy)
would do it.
Let's say most of your tests use the stubbed response. Then you would have a setUp() method that looks like this:
#Before
public void setUp() {
wareHouseSpy = spy(realWarehouse);
doReturn(false).when(wareHouseSpy).isSomethingMissing();
}
Now let's say you want to undo the stubbed response and use the real implementation in one test:
#Test
public void isSomethingMissing_useRealImplementation() {
// Setup
when(wareHouseSpy.isSomethingMissing()).thenCallRealMethod();
// Test - Uses real implementation
boolean result = wareHouseSpy.isSomethingMissing();
}
It depends whether you are testing with TestNG or JUnit.
JUnit creates a new instance of itself for each test method. You basically don't have to worry about reseting mocks.
With TestNG, you have to reset the mock(s) with Mockito.reset(mockA, mockB, ...) in either an #BeforeMethod or an #AfterMethod
The "normal" way is to re-instantiate things in your "setUp" method. However, if you have a real object that is expensive to construct for some reason, you could do something like this:
public class MyTests {
private static MyBigWarehouse realWarehouse = new MyBigWarehouse();
private MyBigWarehouse warehouseSpy;
#Before
public void setUp() {
warehouseSpy = spy(realWarehouse); // same real object - brand new spy!
doReturn(false).when(wareHouseSpy).isSomethingMissing();
}
#Test
...
#Test
...
#Test
...
}
Maybe I am not following but when you have a real object real:
Object mySpy = spy(real);
Then to "unspy" mySpy... just use real.
As per the documentation, we have
reset(mock);
//at this point the mock forgot any interactions & stubbing
The documentation specifies further
Normally, you don't need to reset your mocks, just create new mocks
for each test method. Instead of #reset() please consider writing
simple, small and focused test methods over lengthy, over-specified
tests.
Here's an example from their github repo which tests this behavior and uses it:
#Test
public void shouldRemoveAllInteractions() throws Exception {
mock.simpleMethod(1);
reset(mock);
verifyZeroInteractions(mock);
}
reference : ResetTest.java
Addressing this piece specifically:
Is there a way, just for the sake of cleaning up after me in case some other tests that run after my tests also use the same instances and might execute a mocked method they didn't ask to mock, to un-mock a method?
If you are using JUnit, the cleanest way to do this is to use #Before and #After (other frameworks have equivalents) and recreate the instance and the spy so that no test depends on or is impacted by whatever you have done on any other test. Then you can do the test-specific configuration of the spy/mock inside of each test. If for some reason you don't want to recreate the object, you can recreate the spy. Either way, everyone starts with a fresh spy each time.

#Before and #After exclusion

I'm writing some tests for my DAO, and because a lot of the tests use a test object that is being saved to my database I've created a setup() and teardown() method with the annotations #Before and #After respectively to avoid redundant code, but one of the tests, actually one that doesn't really need the test object, calls a method in the DAO that contains the call getCurrentSession().clear() (it's a method that uses ScrollableResults to get data from the db in batches, and to avoid the memory to fill up it calls flush() and clear() every 50 rows). This creates a problem, because the clear() actually removes the test object that is created in setup() from the session, so when teardown() is called I get an error:
org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [nl.ru.cmbi.pdbeter.core.model.domain.PDBEntry#395]
Is there a way to tell JUnit to not use the setup() and teardown() on this test, or is it better to put all the tests that don't actually need the setup() and teardown() in a new test class?
First of all yes, it makes a lot of sense to isolate tests that don't need the #Before or #After behavior in a separate test.
Secondly, you may want to take a look at the Spring Framework's support for running unit tests within a database transaction that is automatically rolled back at the end of each test, so that you do not have to ever worry about some tests affecting the state of an external resource, or ask questions about which tests are being run in each order, etc. Combine this with an in-memory database (like HSQL) and you won't even need to worry about having a running database somewhere to run against, making your build much more portable.
JUnit will run all methods annotated with #Before and #After for each test so you will need to split your tests into two classes.
Define your own BlockJUnit4ClassRunner:
public class WithoutBeforeAfter extends BlockJUnit4ClassRunner {
public WithoutBeforeAfter(Class<?> klass) throws InitializationError {
super(klass);
}
#Override
protected Statement withBefores(FrameworkMethod method, Object target, Statement statement) {
if(method.getName().equals("methodNameIgnore#Before")){
return statement;
}else{
return super.withBefores(method, target, statement);
}
}
#Override
protected Statement withAfters(FrameworkMethod method, Object target, Statement statement) {
if(method.getName().equals("methodNameIgnore#After")){
return statement;
}else{
return super.withAfters(method, target, statement);
}
}
}
Then use it in your test case:
#RunWith(value=WithoutBeforeAfter.class)
At least it is available in JUnit 4.8.

Categories

Resources