JUnit4 Run A method After Some Methods? - java

I have a method that is not a regular test method. It is a cleanup method. I want to run it after some methods (some methods that are not test methods but are called from some test methods ).
How can do that using JUnit4?
PS: After and AfterClass are not a choice. I want to run a method after "some" non test methods (some methods that are called within test methods).

have you tried #AfterClass And #After ,#Before ,#BeforeClass ?
for the case of #AfterClass your method should be static .
in these case your method would be launched once before all the Tests.
check this link.
junit-beforeclass-and-afterclass-behavior-in-case-of-multiple-test-cases

You will need to call those methods manually or through AOP if you are using Spring.

You could use a TestWatcher to listen to when the test has finished, & check the test-name to see if your code should be ran. E.g.:
#Rule
public TestRule runFooSomtimes = new TestWatcher() {
public void foo() {
//do stuff here
}
List<String> methodsToCheck = new ArrayList<String>() {{
add("testMethodOne");
}}
#Override
protected void finished(Description description) {
if(methodsToCheck.contains(description.getMethodName())) {
foo();
}
}
};
(Excuse any errors, away from an IDE at the moment, but should give an idea.)

Related

How to have multiple setups for different sets of JUnit Tests?

I have just started learning JUnit very recently and came across the following problem.
Have a look at the following class
class MyClass {
String a;
public MyClass(String a) {
this.a=a;
String doSomething(String a) {
if( a.isEmpty() )
return "isEmpty";
else
return"isNotEmpty";
}
I want to test the above method for both the conditions. If I proceed with the general structure of writing testcases it will look something like this:
class MyClassTest {
MyClass myClass;
#BeforeEach
void setUp() {
myClass=new MyClass("sampleString");
}
#Test
void doSomethingTest() {
Assertions.equal("isNotEmpty", myClass.doSomething());
}
}
However, for testing the empty string condition I will need another setup method where instead of "sampleString" I pass an empty string.
Following are the approaches I could think of and the questions for each:
Not use setUp at all and instead initialize the class in the individual test method. However, if let's say there are 10 testcases; 5 of which require empty string and rest "sampleString" then this doesn't make sense. Again, we can have a separate method for this repetitive code and call it individually in each testcase but then that defeats the purpose of having a steup method. Lets say I wanted to use two different setup methods, is there a way to do so?
Have a parameterized setup. I don't know if this is possible though. If yes, please share some useful links for this.
Use TestFactory. I tried reading up about this, but couldn't find an example for this specific case. If you have any, please share.
This example has been kept simple for illustrative purposes.
Group the tests with the same setup in an inner class annotated with #Nested. Each nested test class can have its own setup in a local #BeforeEach method.
You can always prepare the non-common data inside your test method. I've always thought it's easier this way, compared to using parameterized tests. You can't mix parameterized and non-parameterized tests in 1 file.
#Test
void doSomething_nullString()
{
myClass = new MyClass(null);
Assert.assertNull(myClass.doSomething());
}
#Test
void doSomething_emptyString()
{
myClass = new MyClass("");
Assert.assertEquals("", myClass.doSomething());
}
#Test
void doSomething_nonEmptyString()
{
myClass = new MyClass("sampleString");
Assert.assertEquals("sampleString", myClass.doSomething());
}
Or, you can always have helper methods inside the test class.
private MyClass createTestObject_nonNullString() {
return new MyClass("nonNullString");
}
private MyClass createTestObject_nullString() {
return new MyClass(null);
}
#Test
public void doSomething_sample() {
MyClass test = createTestObject_nonNullString();
// perform test
}

Junit #AfterClass (non static)

Junit's #BeforeClass and #AfterClass must be declared static. There is a nice workaround here for #BeforeClass. I have a number of unit tests in my class and only want to initialize and clean up once. Any help on how to get a workaround for #AfterClass? I'd like to use Junit without introducing additional dependencies. Thanks!
If you want something similar to the workaround mentioned for #BeforeClass, you could keep track of how many tests have been ran, then once all tests have been ran finally execute your ending cleanup code.
public class MyTestClass {
// ...
private static int totalTests;
private int testsRan;
// ...
#BeforeClass
public static void beforeClass() {
totalTests = 0;
Method[] methods = MyTestClass.class.getMethods();
for (Method method : methods) {
if (method.getAnnotation(Test.class) != null) {
totalTests++;
}
}
}
// test cases...
#After
public void after() {
testsRan++;
if (testsRan == totalTests) {
// One time clean up code here...
}
}
}
This assumes you're using JUnit 4. If you need to account for methods inherited from a superclass, see this as this solution does not get inherited methods.

Run TestCase from java and display results on Eclipse JUnit view

I defined some classes with, each one, several public methods with #Test annotation. All methods follow the same behavioral pattern (retrieve ressources from IDs, test if empty, log, call the real test for each line on the resource). So, I've externalized this behavior in an abstract class I instanciate on each method, like this:
#Test
public void someTest(){
new BasicTestPattern("X","Y","Z"){ // some parameters to retrieve resources
#Override
protected void testLine(){
someCheck1();
someCheck2();
}
}.run();
}
This solution eliminate 10-30 lines per test method.
Now, I want to go further with a custom annotation, like that:
#TestPattern(param1="X",param2="Y",param3="Z")
public void someTest(){
someCheck1();
someCheck2();
}
Finally I created a little framework to retrieve all the methods with this new annotation in order to instanciate BasicTestPattern and execute it. It is executed well in a TestCase subclass, like that:
TestCase junit_test = new TestCase(){
#Override
public void runTest() {
pattern.run();
}
};
junit_test.run();
However, no Test is displayed/listed in the JUnit view from Eclipse. I see only the number of tests succeeded.
How can I do that ? Thank you.
You probably will need to make your own custom Runner to find all the methods annotated with your #TestPattern method. (and probably also with #Test ?)
Then your test class will look like this:
#RunWith(YourRunner.class)
public class YourTest{
#TestPattern(param1="X",param2="Y",param3="Z")
public void someTest(){
...
}
#Test
public void anotherNormalTest(){
...
}
}
This Blog explains how to write custom Runners. But you can probably get away with extending BlockJUnit4ClassRunner to add the your special test methods to the list of tests to run.
I think you would only have to override the computeTestMethods() method which is how BlockJUnit4ClassRunner finds all the test methods to run (the methods annotated with #Test) you can override it to find the methods you annotated with your own annotation.
public class your TestRunner extends BlockJUnit4ClassRunner{
protected List<FrameworkMethod> computeTestMethods() {
//this is all the #Test annotated methods
List<FrameworkMethod> testAnnotatedMethods = super.computeTestMethods();
//these are all the methods with your #TestPattern annotation
List<FrameworkMethod> yourAnnotatedMethods = getTestClass().getAnnotatedMethods(TestPattern.class);
//do whatever you need to do to generate the test
//methods with the correct parameters based on
//the annotation ?
//Might need to make fake or
//synthetic FrameworkMethod instances?
...
//combine everyting into a single List
List<FrameworkMethod> allTestMethods =...
//finally return all the FrameworkMethods as a single list
return allTestMethods;
}
}
You might have to make your own FrameworkMethod implementation wrapper to get the info from the annotation and do whatever set up is required before invoking the method.
This will make it seamlessly integrate with normal JUnit classes and work with the JUnit IDE view
Good Luck

How to test a static method without running a piece of code in it

A piece of code is like this:
public class ClassToTest {
public static A method1(arguments here){
//a log of code here
A a = new A();
return a;
}
}
The problem is the constructor call new A() is in a library and I don't want method1 to call this constructor in my test because it is not necessary for my current test and it contains some network connections. I want my unit test get rid of any external dependencies.
Generally in a unit test, we don't want to do any modification to the source code. But in order to test the critical logic in method1, It is acceptable to make some reasonable change to the source code.
At first I think I could move the new A() to another method and build a subclass and then override that method. This change is also reasonable without considering testing so I think it is acceptable. But adding a flag for test only is not acceptable.
But I cannot do this because the method I need to test is static.
Is there any other way to test this piece of code without running the line A a = new A()?
If you don't want that method to introduce state, then use PowerMockito.mockStatic() to mock the return value. This makes the assumption that your static method has no side effects, and if it doesn't, you really should write it so that it doesn't.
#RunWith(PowerMockRunner.class)
public class ClassToTestTest {
private ClassToTest classMock;
private ClassToTest testObject;
#Before
public void init() {
testObject = new ClassToTest();
}
#Test
public void example() {
Object args = new Object();
PowerMockito.mockStatic(ClassToTest.class);
doReturn(new A()).when(ClassToTest.class, "method1", args);
}
}
doReturn will allow you to set up what it's going to ultimately give back after execution of your static method.

Get method invocated inside a method in Java

I want to make a JUnit test to assure that some classes don't use a specific set of methods (from another classes). Example
class MyClass
{
void myMethod()
{
otherClass.otherClassStaticMethod();
}
}
class myTest
{
void test()
{
assertFalse(CalledMethods.getMethodsCalledBy("myClass.myMethod").Contains("otherClass.otherClassStaticMethod"));
}
}
In this test I want to assure that myMethod doesn't invocate otherClassStaticMethod. How can I find what methods are being called inside a method in compile time (ignore methods called using reflection)? I thought about a .java parser, do you recommend any?
you can mock "otherClass" and verify that the method isn't invoked. E.g. using Mockito you can even specify in which order what methods are supposed to be invoked (under the condition their instances are mocks) and specify which methods are not allowed to be invoked
as coding.mof said, to mock static methods you should use PowerMock/PowerMockito:
example:
PowerMockito.mockStatic(OtherClass.class);
PowerMockito.verifyStatic(never());
OtherClass.otherClassStaticMethod();
It sounds like you should be using a mock library and let that handle it all for you. I'd recommend JMock as my library of choice. If you're using instance methods then this would be perfect for you - if, as your example shows, it's static methods then PowerMock may work*1.
With JMock, you'd have something like:
public class MyClass {
public MyClass(Dependency dependency) {
this.dependency = dependency;
}
void myMethod() {
dependency.someMethod();
}
}
#RunWith(JMock.class)
public class MyTest {
private Mockery context = new Mockery();
#Test
public void doesNotCallSomeMethod() {
Dependency dependency = context.mock(Dependency.class);
MyClass obj = new MyClass(dependency);
obj.myMethod(); <--- this will fail fast
}
}
When you call obj.myMethod, JMock will instantly report that you never said dependency should have any methods called. It will also tell you what method you DID call and what parameters you passed in if any
*1 I don't use PowerMock as I steer away from static methods unless they are pure functions

Categories