TestNG: Collaborators local to a test - java

Suppose I have one test class with three test methods. The tests may either run serially or in two separate threads. Each test method requires its own instance of a collaborator (such as a resource of some kind). However, this would not seem to cut it:
public class MyTestClass {
private Resource resource;
#BeforeMethod public void setupResource() {}
#AfterMethod public void tearDownResource() {}
#Test public void testMethod1() {}
#Test public void testMethod2() {}
#Test public void testMethod3() {}
}
This seems to work when run serially, but if we run the three test methods in parallel (with method granularity), it would seem that because all three tests are invoked via the same instance, the resource variable ends up being overwritten repeatedly.
So, how about this:
public class MyTestClass {
private static ThreadLocal<Resource> resource;
#BeforeMethod public void setupResource() {}
#AfterMethod public void tearDownResource() {}
#Test public void testMethod1() {}
#Test public void testMethod2() {}
#Test public void testMethod3() {}
}
This seems plausible, and it looks like it can old up if I throw in #DataProvider and test listeners as well (provided setupResource() and tearDownResource() is properly implemented, so that if there are two threads to run tests on, the third method doesn't have any "leftovers" from the first).
Having said that, it seems quite cumbersome to have a #BeforeMethod, an #AfterMethod, and wrapping the collaborator (Resource) in a ThreadLocal. Is there any other good "test-local" alternatives worthy of consideration?

I think you can set up a threadlocal container separately. Something like below; create a Mythreadlocal container class.
public class ThreadLocalContextObject{
private Resource resource;
// getter and setter for above
}
public class MyThreadLocal {
public static final ThreadLocal threadLocal = new ThreadLocal();
public static void set(ThreadLocalContextObject ctx) {
threadLocal.set(ctx);
}
public static void unset() {
threadLocal.remove();
}
public static ThreadLocalContextObject get() {
return threadLocal.get();
}
}
Then from #BeforeMethod you can set the context object holding the resource in the MyThreadLocal. And from the #AfterMethod you can unset it from the threadlocal storage by calling unset.
Note unsetting the threadlocal is necessary failing which can easily cause you run out of memory.
The threadlocal will gurantee the local storage of the resource for the thread executing a particular test case.
So answering your question the threadlocal might be the easiest and safest way to do this stuff according to me.

Related

How to use #Before/#BeforeClass with #Autowired field

I have a test case which has an #Autowired field. I would like to have one method for setting up the test case, as it has many #Test-annotated methods that will rely on the same generated data, (for which I need the autowired class).
What's a good way to achieve this?
If I have the #BeforeClass, then I need to make the method static, which breaks the autowiring.
1st solution
Use TestNG instead.
#Before* annotations behave this way in TestNG.
No method annotated with #Before* has to be static.
#org.testng.annotations.BeforeClass
public void setUpOnce() {
//I'm not static!
}
2nd solution
And if you don't want to do that, you can use an execution listener from Spring (AbstractTestExecutionListener).
You will have to annotate your test class like this:
#TestExecutionListeners({CustomTestExecutionListener.class})
public class Test {
//Some methods with #Test annotation.
}
And then implement CustomTestExecutionListener with this method:
public void beforeTestClass(TestContext testContext) throws Exception {
//Your before goes here.
}
Self-contained in one file that would look like:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"commonContext.xml" })
#TestExecutionListeners({SimpleTest.class})
public class SimpleTest extends AbstractTestExecutionListener {
#Override
public void beforeTestClass(TestContext testContext) {
System.out.println("In beforeTestClass.");
}
#Test
public void test() {
System.out.println("In test.");
}
}
I came up with the solution of creating a separate initialization method (not setUp) annotated with #PostConstruct. This is not really an elegant solution, but it makes sure that the autowired/injected fields are properly initialized by Spring before using them, (which was the initial problem with the statically #BeforeClass annotated method).

Singleton returning new instance when accessed from test method

I am using Junit 4.12 with PowerMock 1.6 with Mockito. I have also used PowerMockRule library as described here. I am trying to execute initialization code for all of my test cases exactly once as described in this SO Thread. Its executing the initialization code exactly one time however, if I do ServiceInitializer.INSTANCE inside test method it returns me new object. I am not able to understand this behavior. Does anyone have any idea why this is happening? If I execute my code without PowerMockRule Library and run my test with PowerMockRunner then it works fine but in that case my ClassRule is not getting executed.
public class ServiceInitializer extends ExternalResource {
public static final TestRule INSTANCE = new ServiceInitializer();
private final AtomicBoolean started = new AtomicBoolean();
#Override protected void before() throws Throwable {
if (!started.compareAndSet(false, true)) {
return;
}
// Initialization code goes here
System.out.println("ServiceInitializationHelper:"+this); //Print Address #3702c2f1
}
#Override protected void after() {
}
}
class BaseTest{
#Rule
public PowerMockRule powerMockRule = new PowerMockRule();
#ClassRule
public static final TestRule serviceInitializer = ServiceInitializer.INSTANCE;
#Before
public final void preTest() {
// some code
}
#After
public final void postTest() {
//some code
}
}
#PrepareForTest({MyClass.class})
public class MyTest extends BaseTest {
#Test
public void testMethodA_1(){
System.out.println(ServiceInitializer.INSTANCE);//Print Address #54d41c2b
}
}
Update
I printed the classloader for the classes and it turns out for first print statement the classloder was sun.misc.Launcher$AppClassLoader and for the second print statement the classloder was org.powermock.core.classloader.MockClassLoader. How can I solve this?
You don't have a singleton. You have a static INSTANCE variable. Keep in mind that one of those can exist for every classloader you have.
Instead make an enum of ServiceInitializer, like so
public enum ServiceInitializer {
INSTANCE;
// rest of class goes here
}
And rely on the JVM's language contracts to ensure the singleton.
Or, better yet, write your code to handle situations where more than one ServiceInitializer can exist, but it just happens that your program only uses one instance. This is the ideal choice, allowing you to alternate between the real ServiceInitializer and a mock if desired.
Edwin is correct; this is an issue with PowerMock creating a new ClassLoader for every test. I strongly recommend refactoring your code so it can be tested without PoeerMock and switch to Mockito.
These books may be helpful
Working Effectively With Legacy Code
Refactoring to Patterns
In the mean time, you can reference ServiceInitializer from your base class:
public class ServiceInitializer extends ExternalResource {
public static final ServiceInitializer INSTANCE = new ServiceInitializer();
private final AtomicBoolean started = new AtomicBoolean();
#Override protected void before() throws Throwable {
if (!started.compareAndSet(false, true)) {
return;
}
// Initialization code goes here
System.out.println("ServiceInitializationHelper:"+this);
}
#Override protected void after() {
}
}
class BaseTest{
#Rule
public PowerMockRule powerMockRule = new PowerMockRule();
#ClassRule
public static final ServiceInitializer serviceInitializer = ServiceInitializer.INSTANCE;
#Before
public final void preTest() {
// some code
}
#After
public final void postTest() {
//some code
}
}
#PrepareForTest({MyClass.class})
public class MyTest extends BaseTest {
#Test
public void testMethodA_1(){
System.out.println(serviceInitializer);
}
}
Well I finally found the work around for this problem. As explained in my question my class was getting loaded by two different class loaders and thus causing problems for me. In order to resolve my issue I used #PowerMockIgnore annotation in order to defer its loading as follows:
#PowerMockIgnore({"com.mypackage.*"})
class BaseTest{
// Stuff goes here
}
This annotation tells PowerMock to defer the loading of classes with the names supplied to value() to the system classloader. You can read about this annotation from here.

How to reuse existing JUnit tests in another test class?

how can I reuse JUnit tests in another testclass?
For example:
public TestClass1 {
#Test
public void testSomething(){...}
}
public TestClass2 {
#Test
public void testSomethingAndSomethingElse() {
// Somehow execute testSomething()
// and then test something else
}
}
Avoid the scenario, in general. It is prone to making tests much more brittle. If TestClass1 fails, then TestClass2 implicitly fails, which isn't desirable for at least the following reasons:
Code is tested more than once, which wastes execution time.
Tests should not rely on each other, they should be as decoupled as possible
If this becomes a pattern, it will become harder to identify what section of code is broken by looking at which tests are failing, which is part of the point of tests
Occasionally sharing sections of test code is useful, particularly for integration tests. Here's how you might do it without depending on the tests themselves:
public abstract BaseTests {
protected void somethingHelper() {
// Test something
}
}
public TestClass1 extends BaseTests {
#Test
public void testSomething(){
somethingHelper();
}
}
public TestClass2 extends BaseTests {
#Test
public void testSomethingAndSomethingElse() {
somethingHelper();
// and then test something else
}
}
Alternatively, you could use a helper class and avoid the inheritance altogether. Asserts and the like can go in the somethingHelper() method.
Don't call a method from TestClass1 in TestClass2 directly. The test cases become less readable this way, and can lead to spaghetti frittata.
As usual you can:
Extends TestClass2 from TestClass1
Access TestClass1 from TestClass2 using delegation:
Example 1:
// Instantiate TestClass1 inside test method
public TestClass2 {
public void testSomethingAndSomethingElse1() {
new TestClass1().testSomething();
}
}
Example 2:
// Instantiate TestClass1 as a member of TestClass2
public TestClass2 {
private TestClass1 one = new TestClass1();
public void testSomethingAndSomethingElse1() {
one.testSomething();
}
}
This is common to run a test with a different configuration. Do not worry about and go ahead.
At the first step create your own test without considering any configuration:
public abstract BaseTests {
#Test
protected void somethingHelper() {
// Test something
}
}
Then, extend the test class and add some configuration:
public TestClass1 extends BaseTests {
#Before
public void setup(){
// TODO: config
}
}
It is not necessary to do specific configuration but it is very common with a configurable system (the main functionality of the system must be valid for each config).
In the other test case:
public TestClass2 extends BaseTests {
#Before
public void setup(){
// TODO: other config
}
}
For example, there may be an encryption and decryption process where the sequence of encryption>decryption must be identified. On the other hand, there is a different algorithm to use while the test process is unique.
Logically, there is no reason to call one test method from another. Any tool that runs one test would just as easily all tests in the package. But if you need to, you'd call it like any other method in any other class.
What you most likely want to do, is perform some common setup for both test methods. You could put that code in a utility method in a common class, and invoke the common code in both tests.

Junit - Multiple #Before vs. one #Before split up into methods

In a unit test, I need to perform a quite complex setup (this may be a code smell but this is not what this question is about :-)). What I'm interested in is if it is better to have multiple #Before methods performing the setup or just one, which calls helper methods to perform the initialization.
E.g.
#Before
public void setUpClientStub() {
}
#Before
public void setUpObjectUnderTest() {
}
vs.
#Before
public void setUp() {
setUpClientStub();
setUpObjectUnderTest();
}
As has been said in other responses, the order in which JUnit finds methods is not guaranteed, so the execution order of #Before methods can't be guaranteed. The same is true of #Rule, it suffers from the same lack of guarantee. If this will always be the same code, then there isn't any point in splitting into two methods.
If you do have two methods, and more importantly, if you wish to use them from multiple places, then you can combine rules using a RuleChain, which was introduced in 4.10. This allows the specific ordering of rules, such as:
public static class UseRuleChain {
#Rule
public TestRule chain= RuleChain
.outerRule(new LoggingRule("outer rule"))
.around(new LoggingRule("middle rule"))
.around(new LoggingRule("inner rule"));
#Test
public void example() {
assertTrue(true);
}
}
This produces:
starting outer rule
starting middle rule
starting inner rule
finished inner rule
finished middle rule
finished outer rule
So you can either upgrade to 4.10 or just steal the class.
In your case, you could define two rules, one for client setup and one for object, and combine them in a RuleChain. Using ExternalResource.
public static class UsesExternalResource {
private TestRule clientRule = new ExternalResource() {
#Override
protected void before() throws Throwable {
setupClientCode();
};
#Override
protected void after() {
tearDownClientCode()
};
};
#Rule public TestRule chain = RuleChain
.outerRule(clientRule)
.around(objectRule);
}
So you'll have the following execution order:
clientRule.before()
objectRule.before()
the test
objectRule.after()
clientRule.after()
I would do the latter. AFAIK, there is no way to guarantee order of #Before annotated setup methods.
Note that there are no guarantees about the order in which #Before annotated methods are invoked. If there are some dependencies between them (e.g. one method must be called before the other), you must use the latter form.
Otherwise this is a matter of preference, just keep them in a single place so it is easy to spot them.
I don't think it makes much of a difference, but I personally prefer the second one (the order Before methods are executed being not defined, you'll have a better control that way).
For me it seems using JUnit 4.12, the methods annotated with #Before get indeed sorted deterministically by the following characteristic:
by reversed lexicographic order with respect to the method name.
You can see this behaviour by executing this Testclass:
import java.util.Arrays;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
/*
* key points:
* - multiple #Before methods get sorted by reversed lexicographic order
* */
public class JUnitLifecyle {
#BeforeClass
public static void runsOnceBeforeClassIsInited() {
System.out.println("#BeforeClass");
}
public JUnitLifecyle() {
System.out.println("Constructor");
}
#Before
public void a() {
System.out.println("#Before a");
}
#Before
public void b() {
System.out.println("#Before b");
}
#Before
public void cd() {
System.out.println("#Before cd");
}
#Before
public void ca() {
System.out.println("#Before ca");
}
#Before
public void cc() {
System.out.println("#Before cc");
}
#Before
public void d() {
System.out.println("#Before d");
}
#Before
public void e() {
System.out.println("#Before e");
}
#Test
public void firstTest() {
System.out.println("#Test 1");
}
#Test
public void secondTest() {
System.out.println("#Test 2");
}
#After
public void runsAfterEveryTestMethod() {
System.out.println("#After");
}
#AfterClass
public static void runsOnceAfterClass() {
System.out.println("#AfterClass");
}
}
I came to this conclusion after playing around with the output, while changing the method names of the methods annotated with #Before.
Keeping this reversed lexicographic order in mind you could name your methods accordingly to let JUnit execute your setup tasks in the right order.
Although the above approach is possible, I think you should not do this in your tests, because the Java-Annotations thing in JUnit was introduced to get away from convention-based testing.
I declared all my #Before methods private and created a single method annotated with #Before that called all those and my tests worked. I have worked in kotlin.
Here's how you can do it:
private fun setUpClientStub() {
//whatever you want to do
}
private fun setUpObjectUnderTest() {
//whatever you want to do
}
#Before
fun setUp() {
setUpClientStub()
setUpObjectUnderTest()
}
#Test
fun test() {
//your test logic
}
This way you can ensure that your methods are called in the right order and you can name them any way you want.

Loading configuration only once before a set of test cases

I have a java package which contains all my test case classes. Each class contains a lot of test cases. Each class is loaded and run one by one by JUnit. However each of the classes contains common configuration code which is run again and again and initialised everytime each of the classes are run.
These initializations take a lot of time.
Is there some way to load these configuration changes first and then run the test case so that I do not need to load them everytime.
JUnit4 has #BeforeClass annotation.
Just do something like this:
public class TestClass {
private static SomeConnection connection;
#BeforeClass
public static void setUp() {
//do common setup
connection = new SomeConnection();
}
#Test
public void testSomething() { }
#Test
public void testSomethingElse() { }
#AfterClass
public static void tearDown() {
//do teardown operations
connection.close();
}
}
Method marked with #BeforeClass will run only once. Just make sure you use JUnit4.
Update:
Also note, that it should be static, and as #ChristopheRoussy mentioned, you can use #AfterClass to destroy your common setup.
You can create a static method that is run before the tests within the class are ran.
#BeforeClass
public static void ranOnlyOnce() {
/*...*/
}
Moreover, if you want to run this once before all of your tests, then you should group your tests in a suite, and put this method in this class, and use JUnit to run the suite instead of the tests.
#RunWith(Suite.class)
#SuiteClasses(value = { Test1.class, ... , Testn.class })
public class AllTests {
#BeforeClass
public static void beforeAllTests() {
/*...*/
}
}
Note that annotations can be used only in Junit 4+.
I would recommend grouping your tests into a testsuite and doing the initialization from the testsuite. There is a good discussion of the possibilities here http://www.xoriant.com/blog/software-testing-and-qa/using-customized-junit-testsuite-for-testing.html
There are a number of possibilities. The first and easiest is to use #BeforeClass and #AfterClass as has been suggested by Matyas and jFrenetic. This is the easiest way to do it if none of the test classes share setup code.
If the classes share the same setup and teardown, look at using the TestRule, specifically the ExternalResource, which allows you to run code before and after each class. The difference between this and #BeforeClass and #AfterClass is that it uses the same class, and therefore the code can be shared more easily. This can be done for example:
#RunWith(Suite.class)
#SuiteClasses({A.class, B.class, C.class})
public class UsesExternalResource {
public static Server myServer= new Server();
#ClassRule
public static ExternalResource resource= new ExternalResource() {
#Override
protected void before() throws Throwable {
myServer.connect();
};
#Override
protected void after() {
myServer.disconnect();
};
};
}
This works in a test class as well, so you could have different, but shared setups for different classes.

Categories

Resources