I'm experiencing some difficulties using JUnit 4.5 in Eclipse, when I use #Before annotation it just does nothing (I may use setUp() which works of course, but I'm just wondering what is wrong), while it works perfectly in Netbeans.. Any thoughts?
Because I cam here via a Google Search, and had to dig quite a bit deeper to see the actual solution:
As #Pace said in the comments, if you extend TestCase, Eclipse treats the Test as JUnit Version 3 or older, and does not respect the #Before annotation - also descripred here: JUnit + Maven + Eclipse: Why #BeforeClass does not work?
Hence, removing the extend TestCase causes fixes the problem
If you are using JUnit 4, you can just annotate the test class or the test method with #Test annotation, instead of extending TestCase.
Since you are using JUnit 4+ there are two ways to write a test case
1 > You make your test class extend TestCase. In this case classes corresponding to Junit 3 are picked up which are not aware of #Before annotation. In this case you will have to override
/**
* Sets up the fixture, for example, open a network connection.
* This method is called before a test is executed.
*/
protected void setUp() throws Exception {
}
2 > use annotations. use #Test annotation for the method in the test class that you are interested in running as a test. There is no need for your class to extend TestCase. Also you do not have to override any method. Simply define your own method that has the logic to be executed before the test method runs and annotate it with #Before annotation.
Related
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.
I am creating junit test cases for my project. I have the below code, where I would like to create a mock,
String propertyFilePath = System.getProperty("path.to.properties");
Resource propertyFile = new FileSystemResourceLoader().getResource(propertyFilePath);
Properties properties = PropertiesLoaderUtils.loadProperties(propertyFile);
I am using junit and mockito-core jar. I tried with below code,
System.setProperty("path.to.properties", "dummyPathToProperties"); //invalid Path
Properties properties = mock(Properties.class);
Resource propertyFile = new FileSystemResourceLoader().getResource("dummyPathToProperties");
when(PropertiesLoaderUtils.loadProperties(propertyFile)).thenReturn(properties);
With above code it throws error when mocking loadProperties method. How can I mock a spring static class and return my mock properties object ?
Any help will be really appreciated.
Mocking static methods requires you to go down the full nine yards and make use of PowerMock. The exact steps to mock static methods are outlined in their documentation for example.
In essence:
Use the #RunWith(PowerMockRunner.class) annotation at the class-level of the test case.
Use the #PrepareForTest(ClassThatContainsStaticMethod.class) annotation at the class-level of the test case.
Use PowerMock.mockStatic(ClassThatContainsStaticMethod.class) to mock all methods of this class.
Use PowerMock.replay(ClassThatContainsStaticMethod.class) to change the class to replay mode.
Use PowerMock.verify(ClassThatContainsStaticMethod.class) to change the class to verify mode.
But of course: consider not using PowerMock; by changing your code so that you don't have to mock the static call. But of course, it is kinda weird to add a wrapper around such a framework-provided static method.
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.
I was going through the documentation for junit tests but am unable to understand the need for defining tests as public.Could anyone share some info on this?
I read on https://github.com/junit-team/junit/blob/master/src/main/java/org/junit/Test.java
But am still not clear with the reason.
With is I meant why can't I write something as
#Test
private void testAdd(){ }
The JUnit framework calls your test methods from outside your test class. If your test methods are private, it won't be able to do that.
"Test classes, test methods, and lifecycle methods are not required to be public, but they must not be private."
Ref. the doc:
https://junit.org/junit5/docs/current/user-guide/#writing-tests-classes-and-methods
JUnit accesses your test methods by reflection. A SecurityManager can control access to private methods. Hence JUnit uses only public methods and fields for anything that is accessed by the framework.
In short: JUnit would fail to run private test methods if a SecurityManager is active that does not allow access to private methods.
try
#Test
public void testAdd(){ }
your testAdd method is private, it won't be able to do that.
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{
}