Powermock verifyPrivate does not work with any() - java

I have a private method whose invocation I want to test without caring about the arguments. I want to test if it was called at all or not.
MyClass.java
public void doStuff(){
unload(args);
}
private void unload(List<String> args) {
//
}
So I used following:
MyClasstest.java
MyClass myClass = PowerMockito.spy(new MyClass());
myClass.doStuff();
verifyPrivate(myClass, times(1)).invoke("unload",any(List.class));
// verifyPrivate(myClass, times(1)).invoke("unload",any()); //same result with this
This test fails with following exception:
Wanted but not invoked com.MyClass.unload(
null );
However, there were other interactions with this mock .......
(actual values with which it was called)
Can verifyPrivate be called with only actual arguments & not with any()?

Here is a working example of what you are trying to do:
You might just missing the #PrepareForTest annotation, which has to point to the correct class. If your class is an external one use #PrepareForTest(MyClass.class), the example below shows it with an internal class.
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyClassTest.class)
public class MyClassTest {
static class MyClass {
public void doStuff(){
unload(null);
}
private void unload(List<String> args) {
}
}
#Test
public void test() throws Exception {
MyClass myClass = PowerMockito.spy(new MyClass());
myClass.doStuff();
PowerMockito.verifyPrivate(myClass, Mockito.times(1)).invoke("unload", Mockito.any());
}
}
Note that you should consider whether you really want to do this in a UnitTest. Normally your UnitTest should not be concerned about whether a private method is used or not, it should be focused on verifying that the correct result is returned or the correct object state is reached.
By adding knowledge about the internal behaviour of the class into it, you test is tightly coupled to the implementation which might not be a good thing.

Related

Mocking static method in Java

Is there way to mock for unit test static method in Java without executing the method actual implementation? Actual implementation launches the process that cannot be done in unit test context.
public class MyExecutor {
public static int execute(...) {
Process pr = Runtime.getRuntime().exec(...)
int status = pr.waitFor();
return status;
}
public MyClass {
public void methodToUnitTest(...){
MyExecutor.execute(...)
}
I want to mock MyExecutor.execute and verify both its invocation and its params when unit testing MyClass.methodToUnitTest but without actual execution of this method.
I read that PowerMockito can mock static method but it does not prevent actual implementation from being executed.
Wrap the static class MyExecutor in a non-static class. Extract the methods of your new non-static class into an interface. Replace the dependencies to static class with the interface - use dependency injection to provide MyExecutor instances to MyClass:
public MyExecutorAdapter implements Executor{
public void execute() {
MyExecutor.execute() //call to static code
}
}
public MyClass {
private Executor myExecutor;
public MyClass(Executor myExecutor){ //MyExecutorAdapter instance can be injected here
this.myExecutor = myExecutor;
}
public void methodToUnitTest(...){
myExecutor.execute(...)
}
}
Now, with the interface, you can easily mock or provide a fake implementation for testing purposes. In your case, you probably need to have a mock to check if the execute method was called.
This is basically known as Adapter pattern

Test tightly coupled classes in Java

I have this original code:
public SomeClass(int parameter) {
this.someProperty = parameter;
this.apiObject = new SomeApiClass(someProperty);
for(i=0; i < 2; i++)
apiObject.setApiProperty(i, "Hello World");
}
The code works perfectly fine. But the problem arises when I try to test the same.
#Mock
private SomeApiClass someApiClass;
private SomeClass someClass;
#Before
public void setUp() throws Exception {
someClass = new SomeClass(3);
}
#Test
public void shouldCreateSomeClass() {
verify(someApiClass, times(2)). setApiProperty(anyInt(),anyString());
}
I understand why this test wouldn't pass. This would work if I change the constructor to this:
public SomeClass(int parameter, SomeApiClass someApiClass) {
...
}
How do I test the original code if I do not want to inject SomeApiClass to the constructor and also can't afford to provide any getters in it.
PS: Please ignore typos in the code. Typed it on the fly.
It's good to think about testability when you design your class and also to differentiate parameters and dependencies.
Dependencies are objects that the class will rely on to get its work done. They generally don't change throughout the lifecycle of the dependee object.
Parameters are more localized than dependencies. They are expected to change in between calls to the methods of the object.
In the original code, it looks like the work done in the constructor for SomeClass should really go inside a method:
public class SomeClass {
public void doWork(int parameter) {
//
}
}
Inside the method, if you are only interested in instantiating SomeApiObject with the parameter, then why not follow the Law of Demeter and pass in directly SomeApiObject as a parameter:
public void doWork(SomeApiObject someApiObject) {
//
}
Then the consumer does the work:
someClass.doWork(new SomeApiObject(3));
and it can be tested by passing in a mocked SomeApiObject as a parameter:
//act
someClass.doWork(mockedSomeApiObject);
//assert
verify(mockedSomeApiObject).someVerification();
However, if you want a combination of parameters and dependencies you can use a Factory as a dependency:
public class SomeClass {
private final SomeApiObjectFactory someApiObjectFactory;
public SomeClass(SomeApiObjectFactory someApiObjectFactory) {
this.someApiObjectFactory = someApiObjectFactory;
}
public void doWork(int parameter) {
SomeApiObject someApiObject = someApiObjectFactory.create(parameter);
//etc
}
Then you can now test the class since you have a way to supply mocks on which behaviour can be verified:
SomeApiObject mockSomeApiObject = Mockito.mock(SomeApiObject.class);
when(mockSomeApiObjectFactory.create(anyInt()).thenReturn(mockApiObject);
Aside from all of that there are ways of using Powermockito to test your original class as it is without alteration but these are not ideal and it is best to refactor if possible so you can use plain Mockito to test. This will give you good OO habits. Good luck!

How do I mock invocations to methods in super class using jMockit

I have a scenario in which I have to mock a method in parent class. The method is invoked from the method under test. I have not been able to mock the function using jMockit.
My super class is method is as follows
public abstract class SuperClass {
protected void emailRecipients(List<String> recipients) {
// Email recipients code. I want to mock this function.
}
}
My subclass is as follows
public class MyClass extends SuperClass {
public void methodUnderTest(HttpServletRequest request) {
// Some code here.
List<String> recipients = new ArrayList<>();
recipients.add("foo#example.com");
recipients.add("bar#example.com");
// This needs to be mocked.
this.emailRecipients(recipients);
}
}
I have tried using partial mocks using jMockit's tutorial, but it has not worked for me. My test method is given below.
UPDATE: I implemented Rogerio's suggestion as follows. The implementation still calls the real method. When I debug the instance of mocked class in Eclipse, this is what I see com.project.web.mvc.$Subclass_superClass#6b38c54e
#Test
public void testMethodUnderTest(#Mocked final SuperClass superClass) throws Exception {
final MyClass myClass = new MyClass();
new Expectations(myClass) {{
// .. Other expectations here
superClass.emailRecipients((List<String>) any);
}};
MockHttpServletRequest req = new MockHttpServletRequest();
myClass.methodUnderTest(req);
}
The issue is that when I try to mock the invocation of emailRecipients, it always tries to call the actual function. I am using Java 7, jMockit v1.35, and Maven 3x for our builds.
UPDATE The code is legacy code. As a result, we can't update it. We can not use PowerMock as it is not among the libraries that have been approved by the company. We can use either jMockit or Mockito or a combination of both.
The fact that you want to mock the method from parent class shows that your approach fails the Separation of Concerns/Single responsibility Pattern (SoC/SRP).
The use of PowerMock as suggested by Rajiv Kapoor is possible but this (as any use of PowerMock) would be a surrender to bad design.
You can solve your design problem by applying the Favor Composition over Inheritance principle (FCoI).
To do so you'd change your (most likely) abstract super class into a "normal" class. You'd create an interface that declares all the public and abstract methods in your super class. Your child class would no longer extend the parent class but implement the interface. It would get an instance of the former parent class as dependency and call it's methods providing common behavior as needed.
This dependency can easily mocked without the need of PowerMock.
UPDATE The code is legacy code. As a result, we can't update it.
In that case you are outruled.
The code you have is not unittestable because it is written in an untestable way. Your only chance is to write module and/or acceptance tests (without the use of a mocking framework) covering each and every execution path through your code.
This test will be expensive to create and slow but they will gurad your when refactoring the code to something testable (== changable) later.
see below example
P.S. use Mockito.any(HttpServletRequest.class)instead of Mockito.any(ArrayList.class) for your code
Super Class
public abstract class SuperClass {
protected void emailRecipients(List<String> recipients) {
System.out.println("Emailed!");
}
}
MyClass
public class MyClass extends SuperClass {
public void methodUnderTest() {
// Some code here.
ArrayList<String> recipients = new ArrayList<>();
recipients.add("foo#example.com");
recipients.add("bar#example.com");
// This needs to be mocked.
this.emailRecipients(recipients);
}
}
Test Class
public class TestCase {
MyClass myClass = Mockito.mock(MyClass.class, Mockito.CALLS_REAL_METHODS);
#Before
public void prepare() {
PowerMockito.doNothing().when(myClass).emailRecipients(Mockito.any(ArrayList.class));
/*PowerMockito.doAnswer(new Answer<Void>() {
#Override
public Void answer(InvocationOnMock invocation) throws Throwable {
System.out.println("Custom code");
return null;
}
}).when(myClass).emailRecipients(Mockito.any(ArrayList.class));*/
}
#Test
public void testMethodUnderTest() throws Exception {
myClass.methodUnderTest();
}
}
If you don't want the code in emailRecipients to execute then use doNothing()
else use doAnswer to execute some other code

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.

Running JUnit tests with different data

I have a suite of unit tests. I have a static variable which gets initialized in setup() method. I want to run all my suite of unit tests with two different values of that static variable.
Static variable in setup() gets initialized to an object which is a singleton. So, I can't(I think I can't) use JUnit parametrized tests.
I have to run all the tests with one value of that static variable, and then run all the tests with other value of static variable.
Any ideas on how to do this in an elegant way if possible.
Code below if my description above is not very easy to understand
public class MyClassTest{
private static final Dep_class dep_obj;
public static void setup(){
dep_obj = Dep_class.getInstance("VALUE_1");
//You can have only instance of Dep_class at any time.
//So for second run I need to do a
//dep_obj = Dep_class.getInstance("VALUE_2") and run my tests.
}
public void test_mymethod(){
//do something with dep_obj
}
Try this
#RunWith(Parameterized.class)
public class MyClassTest {
private Object dep_obj;
public MyClassTest(String val) {
dep_obj = val;
}
#Parameters
public static Collection<?> data() {
Object[][] data = { { "val1" }, { "val2" }, { "val3" } };
return Arrays.asList(data);
}
#Test
public void test() {
System.out.println(dep_obj);
}
}
So first of all, I would question why you have a singleton that is initialized in this way. It seems as if adding an argument to your .getInstance(String s) method would add ambiguity and unexpected behavior, as this String argument will just be disregarded after instantiation (unless you're re-instantiating it if the type changes, in which case it will be highly unpredictable at runtime).
In any case, an easy way to do this would be to abstract the test_mymethod() to a parent class and have two child test classes that each instantiate a different instance of the singleton. Since your JVM will not restart, you'll also need something like PowerMock to reset the singleton to a pre-loaded state before running any tests.
So the parent class would look like so (JUnit annotations added):
public abstract class MyAbstractTestClass {
private final Dep_class dep_obj;
#Before
public abstract void setup(){
// Begin by ensuring that the singleton instance is initialized to null -
// this is highly important, since subclasses will not be able to rely on
// an un-initialized state
Whitebox.setInternalState(dep_obj.getInstance(/*default, arbitrary, or null value*/, "instance", null);
// Now leave the actual singleton initialization to child classes
dep_obj = getSingleton();
}
public abstract Dep_class getSingleton();
#Test
public void test_mymethod(){
//do something with dep_obj
}
}
I made a few assumptions with Powermock - namely that your singleton properly checks to see if the instance is null and if so, initializes it. In this case, I'm assuming that the variable name for your instance is "instance". Next, your child classes would look like this:
public class MyTestClass1 extends MyAbstractTestClass {
#Override
public void Dep_class getSingleton() {
return Dep_class.getInstance("VALUE_1");
}
}
public class MyTestClass2 extends MyAbstractTestClass {
#Override
public void Dep_class getSingleton() {
return Dep_class.getInstance("VALUE_2");
}
}
Again, I would strongly encourage you to re-think implementing a singleton in this way. Singletons should be rarely used anyway - an implementation like this on top of a questionable design pattern is an eyebrow raiser. This question goes over some good guidelines for usage - make sure that your singleton fits this criteria.

Categories