How do I share state between JUnit tests? - java

I have a test class extending junit.framework.TestCase with several test methods.Each method opens a HTTP connection to server and exchange request and response json strings.One method gets a response with a string called UID(similar to sessionId) which i need to use in subsequent requests to the server.
I was previously writing that string to a file and my next requests read that file for string.I am running one method at a time.Now I am trying to use that string without file operations.I maintained a hastable(because there are many UIDs to keep track of) in my test class as instance variable for the purpose , but eventually found that class is getting loaded for my each method invocation as my static block is executing everytime.This is causing the loss of those UIDs.
How do I achieve this without writing to file and reading from it?
I doubt whether my heading matches my requirement.Someone please edit it accordingly.

You will need a static variable for this because each test gets its own instance of the test class.
Use this pattern:
private static String uuid;
private void login() {
// Run this only once
if (null != uuid) return;
... talk to your server ...
uuid = responseFromServer.getUuid();
}
#Test
public void testLogin() {
login();
assertNotNull( uuid );
}
#Test
public void someOtherTest() {
login();
... test something else which needs uuid ...
}
#Test
public void testWithoutLogin() {
... usual test code ...
}
This approach makes sure that login() is called for each test that needs it, that it's tested on its own and that you can run each test independently.

JUnit will create a new instance of the class for each test. Consequently you should likely set up and store this info as static to the class, using a #BeforeClass annotated static method.
See this SO answer for more info.

Related

Running only the tests with #MyTest inside java application

I have a TestRunner class:
public class TestRunner {
private String result = "";
public void runTests(List<String> testClassNames) {
for (String testClassName : testClassNames) {
}
}
public String getResult() {
return result;
}
}
Then I have two test classes and I should run only the tests with #MyTest from both classes. getResult() should essentialy return "exampleTest() - OK" or "exampleTest() - FAILED", depending on if the test passes. Test class looks like this:
public class ExampleTests1 {
#MyTest (expected = IllegalStateException.class)
public void test1() {
throw new IllegalStateException();
}
#MyTest (expected = IllegalStateException.class)
public void test2() {
throw new RuntimeException();
}
}
I tried to do it with JUnitCore and Result, but couldn't find a way to get the test method name to add to the result. Is there another way?
You'll have to use reflection in this case.
This is kind of how JUnit works internally:
Since this sounds as a homework/assigment for educational purposes (If you're developing a "real" application - then just use JUnit or TestNG and don't write anything like this by yourself :) ), I won't provide a full solution however this is what you should do:
For each class identified by a className you should get a java.lang.Class that describes this class name. You can use Class.forName(...)
Then you should get all the methods of that class (by reflection) and for each method run the following:
2.1 Check whether the method is marked with an annotation #MyTest. If it doesn't - don't handle it
2.2 Also check whether the method name starts with test (String has startsWith method)
2.3 If you found out that the test class contains test methods, then:
2.3.1 Create an instance of the Test Class (probably you can assume that it has no-ops constructor, then use newInstance())
2.3.2 Run the method (again by reflection). Check the result / surround the execution call with try/catch block to intercept errors.
2.3.3 Print the Result as specified in the assignment :)

How to implement a client that has to login in every 30 min?

I am writing an application which uses the JiraRestClient by atlassian. I cannot create this client on every Jira interaction so I thought of caching this client.
This client performs login in every 35 minutes so I thought of caching it for 30 min and then perform login again.
For that purpose I need a single instance of this client so that all the threads for the Jira interactions can use it. I created a provider class which will keep the time track and will perform the login, if the creation time of the instance is over 30 min, insuring that the instance is always logged in.
public class JiraRestClientProvider {
private static JiraRestClient jiraRestClient;
private static final long EXPIRATION_TIME = 1800L;
private static long creationTime = Instant.now().getEpochSecond();
public static synchronized JiraRestClient getJiraRestClient() {
if (jiraRestClient == null || Instant.now().getEpochSecond() > creationTime + EXPIRATION_TIME) {
return createJiraRestClient();
}
return jiraRestClient;
}
where createJiraRestClient is a private method that reads the credentials, updates the creation time, and updates the private static variable jiraRestClient.
Another class uses this JiraRestClientProvider class to perform the Jira actions like creating issues or commenting on a issue, etc as follows:
JiraRestClientProvider.getJiraRestClient().
getIssueClient().createIssue(issueInput).claim().getKey();
or
JiraRestClientProvider.getJiraRestClient().getIssueClient()
.getIssue(issueKey).claim().getCommentsUri().toString();
Now, while writing unit test for the class that's using this I can not mock the static method getJiraRestClient and therefore unable to write unit tests.
(Also, I cannot use PowerMock).
My question is, is there a way that I can write my provider class such that I will only have single and fresh instance of JiraRestClient for all threads and I can also unit test it?
Yes you can. But not with your design.
Whenever you call:
JiraRestClientProvider.getJiraRestClient()
you automatically tightly-couple any class with the singleton, which means that every time you call your method under test in unit tests it will call the Singleton. There's no way around that unless of course you want to implement PowerMock :).
A quick win to get this is to wrap your singleton under an interface and use dependancy injection to inject it to your classes.
Writting complete plain code this would look like
interface IJiraClientProvider {
JiraRestClient getJiraRestClient();
}
class Wrapper implements IJiraClientProvider {
JiraRestClient getJiraRestClient() {
return JiraRestClientProvider.getJiraRestClient();
}
}
class YourClass {
private IJiraClientProvider jiraClientProvider
public YourClass(IJiraClientProvider jiraClientProvider) {
this.jiraClientProvider = jiraClientProvider;
}
// now you can unit test your code and mock the dependency
}
When you instantiate YourClass you'll have to pass the wrapper:
YourClass cls = new YourClass(new Wrapper());

Powermock - mocking static class members

I'm trying to mock the following class which contains some static members
public class ClientFact {
private static final String BASE_URL = Config.getProperty("prop1");
private static final String USERID = Config.getProperty("prop2");
......................
public static Client createClient() throws AppException {
}
}
but i'm running into issues with the static member variables which are populated by Config.getProperty. This class does a read on a properties file like so
public class Config {
...............
public static String getProperty(Param param) {
String value = null;
if (param != null) {
value = properties.getProperty(param.toString());
}
return value;
}
}
I'm trying to mock this call since i dont care about the loaded properties in my test. This is what ive tried
#RunWith(PowerMockRunner.class)
#PrepareForTest({ClientFact.class})
public class MyTests {
#Test
public void test() {
PowerMock.mockStaticPartial(Config.class, "getProperty");
EasyMock.expect(Config.getProperty(EasyMock.anyObject())).andReturn(EasyMock.anyString()).anyTimes();
PowerMock.mockStatic(ClientFact.class);
}
}
but its giving the following error...
java.lang.NoSuchMethodError: org/easymock/internal/MocksControl.createMock(Ljava/lang/Class;[Ljava/lang/reflect/Method;)Ljava/lang/Object;
at org.powermock.api.easymock.PowerMock.doCreateMock(PowerMock.java:2214)
at org.powermock.api.easymock.PowerMock.doMock(PowerMock.java:2163)
any ideas what im doign wrong here?
A non-answer: consider not making static calls there.
You see, that directly couples that one class to the implementation of that static method in some other class; for no real reason. (and for the record: it seems strange that a USER_ID String is a static field in your ClientFact class. Do you really intend that all ClientFacts are using the same USER_ID?!)
You could replace that static call with a non-static version (for example by introducing an interface); and then you can use dependency injection to make an instance of that interface available to your class under test. And then all your testing works without the need to Powermock.
Long story short: very often (but not always!) the need to turn to Powermock originates in production code which wasn't written to be testable (like in your case). Thus instead of using the big bad Powermock hammer to "fix" your testing problem, you should consider improving your production code.
You might want to listen to those videos to get a better understanding what I am talking about.

JUNIT : run setup only once for a large number of test classes

I have a class, which I use as a basis for my unit tests. In this class I initialize the whole environment for my tests, setting up database mappings, enter a number of database records across multiple tables, etc. That class has a method with a #BeforeClass annotation which does the initialization. Next thing, I extend that class with specific classes in which I have #Test methods.
My question is, since the before class is exactly the same for all these test classes, how can I ensure that they are run only once for all the tests.
One simple solution is that I could keep all the tests in one class. However, the number of tests is huge, also they are categorised based on functional heads. So they are located in different classes. However since they need the exact same setup, they inherit the #BeforeClass. As a result the whole setup is done at least once per test class, taking much more time in total than I would prefer.
I could, though, put them all in various subpackages under one package, hence if there is a way, how I can run set up once for all the tests within that package, it would be great.
With JUnit4 test suite you can do something like this :
#RunWith(Suite.class)
#Suite.SuiteClasses({ Test1IT.class, Test2IT.class })
public class IntegrationTestSuite
{
#BeforeClass
public static void setUp()
{
System.out.println("Runs before all tests in the annotation above.");
}
#AfterClass
public static void tearDown()
{
System.out.println("Runs after all tests in the annotation above.");
}
}
Then you run this class as you would run a normal test class and it will run all of your tests.
JUnit doesn't support this, you will have to use the standard Java work-arounds for singletons: Move the common setup code into a static code block and then call an empty method in this class:
static {
...init code here...
}
public static void init() {} // Empty method to trigger the execution of the block above
Make sure that all tests call init(), for example my putting it into a #BeforeClass method. Or put the static code block into a shared base class.
Alternatively, use a global variable:
private static boolean initialize = true;
public static void init() {
if(!initialize) return;
initialize = false;
...init code here...
}
Create one base class for all tests:
public class BaseTest {
static{
/*** init code here ***/
}
}
and every test should inherit from it:
public class SomeTest extends BaseTest {
}
You can make one BaseTest class with a #BeforeClass method, then have all the other tests inherit from it. This way, when each test object is constructed, #BeforeClass gets executed.
Also avoid executing it just once for all the test suite, since all the test cases should be independent. #BeforeClass should execute only once each test case, not test suite.
If you can tolerate adding spring-test to your project, or you are using it already, then a good approach is to use the technique described here: How to load DBUnit test data once per case with Spring Test
Not sure if anyone still is using JUnit and trying to fix it without using Spring Runner (aka no spring integration). TestNG has this feature. But here is a JUnit based solution.
Create a RunOnce per thread operation like so. This maintains a list of classes for which the operation has run.
public class RunOnceOperation {
private static final ThreadLocal t = new ThreadLocal();
public void run(Function f) {
if (t.get() == null) {
t.set(Arrays.asList(getClass()));
f.apply(0);
} else {
if (!((List) t.get()).contains(getClass())) {
((List) t.get()).add(getClass());
f.apply(0);
}
}
}
}
Back in your unit test
#Before
public beforeTest() {
operation.run(new Function<Integer, Void>() {
#Override
public Void apply(Integer t) {
checkBeanProperties();
return null;
}
});
}
private void checkBeanProperties() {
//I only want to check this once per class.
//Also my bean check needs instance of the class and can't be static.
}
My function interface is like this:
interface Function<I,O> {
O apply(I i);
}
When you use this way, you can perform operations once per class using ThreadLocal.

Passing output of one test method to another method testng

I have to write the following unit test cases in testng:
saveProductTest which would return productId if product details are saved successfully in DB.
modifyProductTest, it should use previously saved productId as a parameter.
I am taking the product details input(PrdouctName, ReleaseDate) for saveProductTest and modifyProductTest method from an XML file using testNg data providers.Since productId is generated in save method, I have to pass it to the modify method.
What is the best way to pass output of one test method to another method in testng.
With all due respect to simendsjo, the fact that all tests should be independent from each other is a dogmatic approach that has a lot of exceptions.
Back to the original question: 1) use dependent methods and 2) store the intermediate result in a field (TestNG doesn't recreate your instances from scratch, so that field will retain its value).
For example
private int mResult;
#Test
public void f1() {
mResult = ...
}
#Test(dependsOnMethods = "f1")
public void f2() {
// use mResult
}
With the ITestContext object. It's a object available globally at the Suite context and disponible via parameter in each #Test.
For example:
#Test
public void test1(ITestContext context, Method method) throws Exception {
// ...
context.setAttribute(Constantes.LISTA_PEDIDOS, listPaisPedidos);
// ...
}
#Test
public void test2(ITestContext context, Method method) throws Exception {
List<PaisPedido> listPaisPedido = (List<PaisPedido>)
context.getAttribute(Constantes.LISTA_PEDIDOS);
// ...
}
Each unit test should be independent of other tests so you more easily can see what fails. You can have a helper method saving the product and returning the id and call this from both tests.

Categories

Resources