0

I have a private method in my java code which needs to be invoked twice. I am writing junits using Powermock. While mocking the said method I need two different results for two different invokations.

//I have tried:

PowerMockito.doReturn("MyString1").doReturn("MyString2").when(spy,"getresult",Mockito.anyString());

//But when() is not accepting anything else than the spy object.

PowerMockito.doReturn("MyString1").doReturn("MyString2").when(spy).getresult(Mockito.anyString());

//when() is not letting to use the method getresult as this getresult method is declared private.

CODE

Class A{
String firstString="abc";
String secondString="def";
String result1=getresult(firstString);
String result2=getresult(secondString);

private String getresult(String arg1){
//My code here;
return "AnyString";
}
}

JUNIT

//Declarations
@InjectMocks
A a;
.......
@Test
public void ATest(){
....
/*Suppose I want "MyString1" and "MyString2" as result for calling the method "getresult" for result1 and result2 in Class A*/
A spy=PowerMockito.spy(a);
PowerMockito.doReturn("MyString1").when(spy,"getresult",Mockito.anyString());
....
}
// Please overlook the typos

I am getting compilation error while using the code that I tried. As written in the comments of code, I am expecting two results "MyString1" and "MyString2" in the two successive method calls as shown in the code.

Thanks in advance. Any other approach to achieve the results is appreciated.

javaDeveloper
  • 1,403
  • 3
  • 28
  • 42
  • you're not supposed to mock private methods – Stultuske Apr 01 '19 at 11:30
  • You should not mock / test private methods, they are an implementation detail of the unit under testing, your test will end up to be a far too tight coupling to the actual implementation. – luk2302 Apr 01 '19 at 11:31
  • In practice, the private method needs a few parameters that is not possible to be provided in junits. That's why I need to mock the method. Thanks. – Swastik Banerjee Apr 01 '19 at 11:37
  • no, that argument is invalid, **private methods do not matter**. The problem is that your class structure is wrong / off. Having fields that initialize themselves with potentially complex methods calls is not a good idea. – luk2302 Apr 01 '19 at 11:55
  • @SwastikBanerjee your private methods are called within your public methods, it's they that pass information to them. "parameters that is not possible to be provided in junits" ... for private methods, is nonsense – Stultuske Apr 01 '19 at 12:01

2 Answers2

1

Let me start with the note that the main reason to use PowerMock is to help testing the Legacy applications. There is literally no place for the PowerMock in a new code. Need for a PowerMock in a new code indicates serious problems in the design.

One of the benefits of unit testing is that the tests provide feedback on your design. If writing such test is overly awkward, fragile or not possible (without PowerMock) you should reconsider your design.

One of the things you can do to test such code is to extract the private method into a separate class and provide it as a dependency. Then you can mock it easily. But you should still test the extracted logic which depends on why you could not setup the test in the first place. You may need integration test or some other approach.

Januson
  • 4,533
  • 34
  • 42
  • "Need for a PowerMock in a new code indicates serious problems in the design". No, that is nonsense. If you don't use a Mocking framework to test your code, you either don't have any service calls, or you don't have any unit tests. Remember, your unit tests are supposed to test the unit, not everything behind it. That's what you have end-2-end tests for. – Stultuske Apr 01 '19 at 12:04
  • 1
    I am talking specifically about the PowerMock, not mocking in general. – Januson Apr 01 '19 at 12:08
  • whether you talk about Mockito or PowerMock, you may want to read up the comments on their official pages before declaring what they're for (PowerMock is not mainly for legacy applications. (not according their page, anyway) – Stultuske Apr 01 '19 at 12:11
  • 1
    @Stultuske Januson's argument is that for new and properly written code something like Mockito should suffice. Having to use a tool that is more powerful (e.g. mocks static methods) indicates that the code is flawed because you should not have to use something more powerful. Wether or not the makers of PowerMock see it that way does not really matter. – luk2302 Apr 01 '19 at 16:23
0

I usually do not test private methods separately. They will be tested by the public method which is calling this private method. If there are multiple flows, write multiple tests in a way where all code paths in the private method are tested.

However the following link shows how to test private methods.

https://dzone.com/articles/mock-private-method

LeoN
  • 1,590
  • 1
  • 11
  • 19