Why should Test methods in Junit be defined public? - junit

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.

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.

Junit test case with Mockito

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.

Deep / Nested Dependency Injection in testing

I am using junit, mockito and mockMVC to test the working of a webapp. I am struggling with a dependency whose injecttion I cannot figure out. My webapp structure is as follows.
Class Controller{
#Autowired Service searchService;
#RequestMapping("Search")
public returnType search(#RequestParam("parameter")String parameter){
searchService.doSearch(parameter);
}
}
and the service class
Class Service{
#Autowired Service2 service2;
public returnType doSearch(String parameter){
//some code
service2.call(parameter);
}
}
I need to test the search method for this controller, however service2 is not currently live and hence calls to it have to be mocked. I can mock service2, but cannot figure out how to inject a mock of service2 in my mockMVC instance of controller. As far as I know #InjectMocks in mockito only injects mocks one level deep and not two.
EDIT:
I am using the following to get MockMVC instance of controller
MockMvc controller;
controller = MockMvcBuilders.standaloneSetup(Controller);
What you are essentially want to do is mock a bean.
In your case, you have to mock bean for service2 using #MockBean annotations.
Please refer this article for details.
You don't need that.
Mocking search service will be sufficient as you get the handle of what needs to be done.
Example:
doReturn(...).when(searchService).doSearch(any());
While performing Unit Testing, the developer need to identify the System Under Test and mock/stub all the collaborators.
So, in this case you would write a separate unit test for Controller and Search Service.
Also, read this brilliant article by Martin Fowler - Mocks Aren't Stubs.

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.

mock cdi interceptors during junit tests

I have a complex Java EE 6 app with a web module, an EJB module and some utility jars.
I want to do some integration tests with Junit. Therefore I use the openwebbeans cdi container (Thanks to Mr. Struberg http://struberg.wordpress.com/2012/03/17/controlling-cdi-containers-in-se-and-ee/)
It works perfectly. I can start a complete cdi container in a Junit test.
My problem is that I have some interceptors in my application which cannot run in a Junit test (MQ-, persistence- and transaction-interceptors). So I want to mock these interceptor implementations.
Does anybody know how to do this?
To whom it may concern ;-)
At the end I solved my issue with clean Java EE techniques. I provided a method which observes the ProcessAnnotatedType event. This method evaluates the type which is processed and if it is one of my interceptors, then I veto the processing.
public void processAnnotatedType(#Observes final ProcessAnnotatedType<?> event, final BeanManager manager) {
if (event.getAnnotatedType().getJavaClass().equals(PrivilegeCheckingInterceptor.class)) {
event.veto();
}
}
Why not just test in the container of choice with Arquillian? The other option which comes to mind would be to add in interceptors with mock functionality and exclude the actual interceptor implementation when you start the CDI container.
You can also run tests with embedded OpenEJB.
This link http://openejb.apache.org/examples-trunk/interceptors/ may be useful - perhaps setting property of 'openejb.deployments.classpath.exclude' could help.
Another option of "vetoing" could be through Deltaspike #Exclude annotation. It can veto beans based on ProjectStage.
Example:
#Exclude(ifProjectStage = ProjectStage.UnitTest.class)
public class MyInterceptor {
}
Then in your test you can activate the project stage using Deltapike test control module, example:
#RunWith(CdiTestRunner.class)
#TestControl(projectStage = UnitTest.class)
public class TestStageControl {
#Test...
}