What is the scope of the #SuppressStaticInitializationFor PowerMock annotation? - junit

Does anyone know what is the scope of this annotation? For example, if I have multiple JUnit test classes that run sequentially in the same VM, and the first test uses #SuppressStaticInitializationFor, does that suppress the static initialization for all the subsequent test classes, too? I ask because I am under the impression that static state persists for the life of the JVM.

The scope is per classloader. Once you've used #SuppressStaticInitializationFor it'll affect the class in all other tests. You can however #SuppressStaticInitializationFor at the method level instead and that way it won't affect other tests.

you can use #SuppressStaticInitializationFor annotation at the class-level or at the method-level of the test where you want it to be suppressed.
#RunWith(PowerMockRunner.class)
#SuppressStaticInitializationFor("com.main.java.CassName")
public class TestClassName extends PowerMockTestCase {
//code
#SuppressStaticInitializationFor("com.main.java.AnotherClassName")
public void testMethod() {
//code
}
}
This way you can control which method should suppress static initializers(constructors) and for which class.

Related

Is there a way to share #Before code between tests suite classes?

I am testing a Cordova plugin in Java/Android and I need to initialize my Plugin class and set some state before I run my Tests.
#Before
public void beforeEach() throws Exception {
System.out.println("Creating new Instance ");
PowerMockito.mockStatic(Helpers.class);
PowerMockito.when(Helpers.canUseStorage(any(), any())).thenReturn(true);
MyLogger myLoggerMock = PowerMockito.mock(MyLogger.class);
PowerMockito.doNothing().when(myLoggerMock, "log", anyString());
PowerMockito.whenNew(MyLogger.class).withAnyArguments().thenReturn(myLoggerMock);
this.sut = spy(new FilePicker());
PowerMockito.doNothing().when(this.sut).pick(any(), any());
}
I want to create a Test Suite / Java Class per public function, but I do not want to repeat that code every time.
Is there a way to share that before each between test suites? I have found ClassRule but I think I do not do what I need (or I am understanding it wrong... I am really new in Java)
In Typescript we can share beforeEachfunctions with several suites, and each suite can have their own beforeEach
One possible ways is using inheritance:
Make all test classes extend from one "parent test" class and define a #Before in a parent class.
So it will be called automatically for all the subclasses:
public class ParentTest {
#Before
public void doInitialization() {
....
}
}
public class Test1Class extends ParentClass {
#Test
public void fooTest() {
// doInitialization will be executed before this method
}
#Test
public void barTest() {
// doInitialization will be executed before this method as well
}
}
Two notes:
Note 1
In the code you use sut (subject under test) - this obviously should not be in the parent's doInitialization method, so its possible that Test1Class will also have methods annotated with #Before (read here for information about ordering and so forth)
Then the `sut gets initialized with Spy which is frankly weird IMHO, the Subject Under Test should be a real class that you wrote, but that's beyond the scope of the question, just mentioning it because it can point on mistake.
Note 2
I'm writing it in an an attempt to help because you've said that you're new in Java, this is not strictly related to your question...
While this approach works in general you should be really cautious with PowerMockito. I'm not a PowerMockito expert and try to avoid this type of mocks in my code but in a nutshell the way it manipulates the byte code can clash with other tools. From your code: you can refactor the HelperUtils to be non-static and thus avoid PowerMocking in favor of regular mocking which is faster and much more safe.
As for the Logging - usually you can compromise on it in unit test, if you're using slf4j library you can config it to use "no-op" log for tests, like sending all the logging messages into "nothing", and not-seeing them in the console.

How to use values from porperty files in a global context with Junit5 and CitrusExtension

Maybe I'm on the wrong course or totally misunderstanding something.
I've merged a Citrus IntegrationTest from Junit4Runner to Junit5 (with CitrusExtension).
There is an EndpointConfiguration class
#Configuration
#PropertySource("test-setup.properties")
#PropertySource("service-paths.properties")
public class RestEndpointConfig {
#Value("${testenv.host}") //defined in test-setup.properties
private String host;
...
}
And a TestClass
#ExtendWith(CitrusExtension.class)
#RunWith(JUnitPlatform.class)
public class BaseIT{
#CitrusEndpoint
protected HttpClient httpClient;
#Value("${rest.session}") //defined in service-paths.properties
private String sessionPath;
}
In the test class I want to access values defined in the service-paths.properties file.
This worked with JUnit4 but after the changes to JUnit5 it seems that the properties are no longer available in a 'global' context.
Turning the log level to 'debug' shows, that the properties file is loaded.
So my question is: What do I need to change in order to get access to the service-paths properies in my IT classes. What am I missing, what is best practice in this case?
Thanks in advance for any feedback.
Property value resolving via #Value annotation is a core Spring framework feature. So you need to add SpringExtension to your JUnit5 test. You can do this in addition to using the CitrusExtension.

Execute code before #Before method for JUnit test

I need to execute some code before the #Before method of each unit test is executed. The problem is that I also need to know which test (the name is sufficient) will be executed afterwards.
I can either use AspectJ or Java Agents with bytecode manipulation to achieve this. Also the solution should work for tests where there is no #Before annotation present.
Any ideas?
EDIT: I can't modify the unit tests themselves, as I'm developing a framework for executing tests of other projects
You might want to look into the TestName rule in JUnit:
http://junit.org/junit4/javadoc/4.12/org/junit/rules/TestName.html
About the ordering, a solution could be to define a super class for your tests and put a #Before in there, as #Before methods in super classes are run before those in sub classes.
If you want to write a Java agent and you are not bound to Javassist or AspectJ, have a look at Byte Buddy for doing so. You can add the code in the MyAdvice class to any method annotated with #Test given that the type name ends with Test (as an example) by:
public class MyAgent {
public static void premain(String arg, Instrumentation inst) {
new AgentBuilder.Default()
.type(nameEndsWith("Test"))
.transform((type, cl, builder) -> builder.visit(Advice
.to(MyAdvice.class)
.on(isAnnotatedWith(Test.class)))
.installOn(instrumentation);
}
}
class MyAdvice {
#Advice.OnMethodEnter
static void enter() {
System.out.println("foo");
}
}
Just bundle the above code to a Javaagent with the proper manifest code and register it before running. If you are running on a JDK, you can also attach the agent programmatically using the byte-buddy-agent project.

How to Create a "Base" Test Method in Junit or TestNG

Given the following:
class TestCase {
#Test
public void test(){
assertTrue(true);
}
}
Is there a way to create a base test method? I have some repetitive code that needs to happen for each test. Or perhaps I am just as well-off writing a utility method and calling it each time in the beginning of each test?
It can't be in a #beforeMethod because I need the info in the test itself.
Sure, just put it in a base class and extend that class (at least for TestNG).

Different Singleton instances with JUnit tests

I have a standalone singleton which successfully passes the test. But with a group of tests this fails since once a singleton is defined it does not allow to reset the instance.
Any ideas about how to go about this?
I assume you have a private static field within your singleton class to store the initialized instance.
If you do not want to modify your code, you can define a teardown method which run after every test, and in this method you set this static field to null via reflection as seen here.
Don't use a singleton.
Specifically, the only difference between a singleton and a global variable is that the singleton tries to enforce a single instance (by making the constructor private, for example).
Instead, make the constructor public and write tests using new instances. In your actual program, use getInstance() to get the canonical global instance (or use an IOC container).
And remember that singletons are pathological liars.
If you're still too comfortable with the idea of a Singleton, instead of making the constructor public you can add a public (and static) factory method to create instances in a way that can't be used by accident, e.g.:
public static MyClass TEST_CreateInstance() {
return new MyClass();
}
Spring provides the DirtiesContext annotation for this particular use case where you need new instances of the singleton beans for each testcase. It basically creates a new application context for each testcase/testclass which has this annotation applied.
You can add a method to destroy the singleton, for example destroyMe(); where you deinitialize everything and set the instance of the singleton to null.
public void destroyMe(){
this.instance = null;
//-- other stuff to turn it off.
}
I will leave synchronization problems though ;)
But why do you need to re-initialize your singleton for each test? It should not differ based on the concept of the singleton.
I highly recommend moving away from Singletons as a design pattern, and using Singleton as a scope (Dependency Injection). This would simply make your problem go away.
But assuming you are stuck in the world of Singletons, then you have a few options depending on if you are testing the Singleton or the dependency.
If you are testing the dependant item then you can mock the Singleton using PowerMock and JMockIt. See my previous post about mocking Runtime.getRuntime for instructions on how to go about this.
If you are testing the Singleton then you need to relax the rules on construction, or give the Singleton a "Reset" method.
generally beware of singletons, most often they are evil, bad design and tend to represent big yucky global variables (which is bad for maintenance).
still to get tests in place first you can do:
static setInstance(...){ //package visibility or in difficult cases you have to use public
instance = ...;
}
as said this is more a workaround. so get first tests place, but then refactor away from singleton pattern.
Singleton instance needs to be passed to SUT by test itself - that way you create singleton (and destroy) for each test. Adopting IoC and mocking framework, like Mockito, would render this approach almost trivial.
Very late to the party here, but for anyone looking for an answer, in case you don't want / cannot modify the code.
#BeforeEach
public void setup() {
object = Singleton.getInstance();
}
#AfterEach
public void after() {
// cleaning the singleton instance
ReflectionTestUtils.setField(object , "internal_object_name", null);
}
your Singleton class should be something like this:
public final class Singleton {
private static Singleton internal_object_name;
private Singleton (){}
public static Singleton getInstance() {
if (object == null)
return new Singleton();
else
return internal_object_name;
}