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

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).

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.

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.

Junit Testing of private methods

I am new to Junit testing, would like to test a private method within a class.But it causing visibility problems.how can i test a private method or protected method using Junit.Or can i test a logic within a constructor with Junit??
Simply do it like this:
private someMethod() {}
public someMethodVisibleToAll() {
someMethod();
}
It's not a good idea to hide complex logic in private methods without any access to test it, try to make methods idempotent (without side effects).
In case of legacy code use Powermock, but first try to refactor to code above, if it's not possible than you Powermock as last emergency break.
Just notice: Protected methods are testbable if you use convention that JUnit test has same package name e.g
code src/main/java
package my.package.first
in JUnit folder src/main/test
package my.package.first
than all your protected methods are available to test
Update:
There should always be a way to test private methods indirectly through public methods or protected which uses or includes using of private methods which are cases for testing. If this isn't true and you are not dependent on legacy or third party code, than it's an alert that something is wrong with class design.

What is the scope of the #SuppressStaticInitializationFor PowerMock annotation?

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.

Why Junit still allow a class extend TestCase to use the annotation #Test in it?

I know in Junit, the class extend TestCase cannot support #Before and #After. But it still allow to use #Test?
I know without #Test, if we want to run this class, we could override the runTest method and define the method to be invoked. This is not convenient. Because if we mark the #Test in method of this class., it could run directly. Can anyone tell me the mechanism about how to invoke the method with #Test about this class?
By the way, If I want put a lot of tests into a TestSuite, Should I choose a class extend TestCase or define a arbitrary class with #Test as the Single Test Class ?
The TestCase class is from Junit 3 and should not be used in Junit 4 + classes.
If you extend TestCase, and use the Junit 3 Test runners then your test method names need to start with the word "test". (Junit 3 test runners use Java reflection to find and invoke all methods that start with the word "test")
Relying on TestClass hindered test class designs because you were forced to extend that class which made somethings hard to test. There also wasn't anything equivalent to Junit4's #BeforeClass or #AfterClass which meant you had to do all the more complicated multi-test fixture set up and tear down yourself.
To run many Junit4 test classes at once as a Test Suite, you can create a new empty class with the #RunWith and #SuiteClasses annotations as shown below:
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
#RunWith(Suite.class)
#SuiteClasses(
{
TestClassA.class,
TestClassB.class
}
)
public class MyTestSuite{
}