Mock a static method - java

I want to write a test case that will verify a method in my class.
I have a local ApplicationLauncher object in my method that has to be mocked because it calls a method, launch(), which should not be called in a unit test.
public class RunApp
{
public void check(String name)
{
if(name !=null)
{
ApplicationLauncher launcher = Application.getLauncher("launch");
String appName = name+".bat";
launcher.launch(appName);
}
}
}
My JUnit test code is below:
RunApp runapp = new RunApp();
#Mock
ApplicationLauncher launcher;
#Test
public void test()
{
runapp.check("test");
verify(launcher,atLeastOnce).launch(anyString());
}
I am not able to return a mock object like
when(Application.getLauncher(anyString())).thenReturn(launcher);
since getLauncher is a static method in Application class. How can I solve this?

A better application design might be to have ApplicationLauncher as an interface and create production and test implementations (or just mock the test implementation). You would need to pass an instance of ApplicationLauncher into your RunApp class, perhaps in the constructor.

You can mock static methods using PowerMock, however you should check whether the static method call is really necessary.

You could refactor your class to accept the launcher to be "injected".
public class RunApp
{
public void check(String name)
{
check(name, Application.getLauncher("launch"));
}
protected check(String name, ApplicationLauncher launcher) {
if (name != null)
{
String appName = name + ".bat";
launcher.launch(appName);
}
}
}
That way you could use the new package-protected check() method to test your code using a fake launcher.

Related

Skip null check in mockito

I am trying to write unit test cases for one of the methods in code.Below is the method
public boolean isValid() {
if(object == null)
return false
//do something here and return value.
}
The object is created by this method which is done before without getter setter method.
private Object returnObject() {
object = Axis2ConfigurationContextFactory.getConfigurationContext();
return object;
}
When I try to test isValid(), the object is always null, so it never goes in the code to do something.
I was checking if there is any way to skip that line or make the object not null. I also tried creating an object using returnObject method. But it uses Axis library classes which throws error if it does not find certain data. What can be done in this case? I am dealing with legacy code so any pointers would be helpful.
Edit : Adding test implementation.
#PowerMockIgnore({ "javax.xml.*", "org.w3c.dom.*", "javax.management.*" })
public class ClassTest {
private ClassTest classTestObj;
#BeforeMethod
public void callClassConstructor() {
classTestObj = //call class constructor
}
#BeforeClass
public void setUpClass() throws Exception {
MockitoAnnotations.initMocks(this);
}
#Test
public boolean isValidTest() {
Boolean result = classTestObj.isValid();
Assert.assertEquals(result);
}
}
As I mentioned in the before comment, you can make use of MockedStatic to mock the static method - https://javadoc.io/static/org.mockito/mockito-core/4.4.0/org/mockito/Mockito.html#static_mocks
So your code will somewhat look like the below one if you are making use of Mockito instead of PowerMockito.
#RunWith(MockitoJUnitRunner.class)
public class ClassTest
{
#Mock
private Object mockAxis2ConfigurationContextFactoryObject;
#Test
public boolean isValidTest() {
try (MockedStatic<Axis2ConfigurationContextFactory> mockedStatic = mockStatic(Axis2ConfigurationContextFactory.class)) {
mockedStatic.when(()->Axis2ConfigurationContextFactory.getConfigurationContext()).thenReturn(mockAxis2ConfigurationContextFactoryObject);
Boolean result = classTestObj.isValid();
Assert.assertEquals(result);
}
}

Is it possible to test static private methods used from public static methods with Mockito (not PowerMockito!)?

I have a public static method which internally uses another static but private method. SonarQube bothers me to test this private method. How can I do this using Mockito (inline)?
public class MyClass {
public static boolean isXxxValid(String value1, String value2) {
try {
var s = myPrivateMethod(anyString);
...
} catch (Exception ex) {
...
}
}
private static String myPrivateMethod(final String input) {
...
}
}
How can I test or mock myPrivateMethod()?
In general the testing of private methods should be done via the business interface (the public methods of your class).
But since you are mentioning powermock I guess your idea is to mock that privat method to test your public method. That would be another anti pattern. You should never mock parts of the class under test.
In your case it seem that you need to mock the external dependencies that are used in your private method.

How to mock a static method in side a public class using Power mockito?

Hi every one I am trying to mock a static method name mapCreditInfo(UCIPin, creditAssessmentResults) which has two parameters UCIPin and creditAssessmentResults. UCIPin is String type and creditAssessmentResults is List
This method is inside a public class ResponseMapper
type as shown below:
private CreditInfo getAccountByUCI(String audiUser, String UCIPin) throws EnterpriseCustomerVerificationException {
List<CreditAssessmentResult> creditAssessmentResults = creditInfoRepository.getUCISummary(UCIPin, audiUser);
return ResponseMapper.mapCreditInfo(UCIPin, creditAssessmentResults);
}
Note: getAccountbyUCI method is called inside another public method
name executeCustomerVerification which is in the class
EnterpriseCustomerVerificationService
ResponseMapper class
public class ResponseMapper {
public static CreditInfo mapCreditInfo(String UCIPin, List<CreditAssessmentResult> creditAssessmentResults) {
CreditInfo creditInfo = new CreditInfo();
creditInfo.setUCIPin(UCIPin);
List<AccountCreditInfo> accountCreditInfos = new ArrayList<AccountCreditInfo>();
for (CreditAssessmentResult creditAssessmentResult : creditAssessmentResults) {
AccountCreditInfo accountCreditInfo = new AccountCreditInfo();
accountCreditInfo.setDelinquenctBalance(creditAssessmentResult.getPastDueAmount());
accountCreditInfo.setNonPayDisconnect(creditAssessmentResult.getNonpayDiscount());
accountCreditInfo.setPreviousAccountNumber(creditAssessmentResult.getAccountNumber());
accountCreditInfo.setUnreturnedEquipmentFlag(creditAssessmentResult.getUnreturnedEquipment());
accountCreditInfos.add(accountCreditInfo);
}
creditInfo.setAccountCreditInfo(accountCreditInfos);
return creditInfo;
}
}
I have Tried like some portion of my test class as shown below :
Test Class
#PrepareForTest( EnterpriseCustomerVerificationService.class)
#RunWith(PowerMockRunner.class)
public class EnterpriseCustomerVerificationServiceTest {
#InjectMocks
private EnterpriseCustomerVerificationService enterpriseCustormerVerificationServiceMock ;
#Test
public void executeCustomerVerificationTest() throws Exception {
List<ErrorResponse> errorResponses = getErrorResponse();
List<String> mso = new ArrayList<String>();
mso.add("a");
mso.add("b");
mso.add("c");
AddressResponse addressResponse = getAddressResponse();
String experianAuthorization = "experianAuthorization";
String UCIPin = "110019";
String auditUser = "ABC";
CreditInfo credit = getCreditInfo();
CreditCheck creditCheck = getcreditCheck();
EnterpriseCustomerVerificationService spy = PowerMockito.spy(new EnterpriseCustomerVerificationService());
PowerMockito.when(spy,PowerMockito.method(EnterpriseCustomerVerificationService.class,"executeCreditCheck",CreditCheck.class)).withArguments(Mockito.any()).thenReturn("#1");
Mockito.when(creditInfoRepository.getUCISummary("110019", "test")).thenReturn(getCreditAssessmentResultList());
PowerMockito.mockStatic(ResponseMapper.class);
Mockito.when(ResponseMapper.mapCreditInfo(UCIPin, getCreditAssessmentResultList())).thenReturn(credit);
CustomerVerification cv = spy
.executeCustomerVerification(getCustomerVerificationRequest1(),
"101");
}
My question is how to mock static mapCreditInfo method using power Mockito ?
Thanks
Like this ...
#RunWith(PowerMockRunner.class)
#PrepareForTest({ResponseMapper.class})
public class ATest {
#Test
public void testMockingStatic() {
PowerMockito.mockStatic(ResponseMapper.class);
// if you want to use specific argument matchers
Mockito.when(ResponseMapper.mapCreditInfo(
uciPin, creditAssessmentResults)
).thenReturn(creditInfo);
// or if you want to match on any arguments passed into your static method ...
Mockito.when(ResponseMapper.mapCreditInfo(
ArgumentMatchers.anyString(),
ArgumentMatchers.anyList())
).thenReturn(creditInfo);
// ...
}
}
Notes:
#PrepareForTest prepares the class with the static methods which you want to mock
PowerMockito.mockStatic mocks all static methods that class
You can use standard Mockito when/then constructs to tell the mocked static methods what to return
The example above uses these dependencies:
org.mockito:mockito-core:2.7.19
org.powermock:powermock-module-junit4:1.7.0
org.powermock:powermock-api-mockito2:1.7.0
Update 1: based on your updated question which shows your test method ...
My example includes: #PrepareForTest({ResponseMapper.class}) your test method is not preparing ResponseMapper instead it is preparing EnterpriseCustomerVerificationService. It's like you are preparing the class which calls the class which has a static method rather than preparing the class which contains the static method.
I would strongly suggest creating a new test case - just temporarily - which looks like the one I have provided and use that to show yourself how to mock a static method and once you are comfortable with that then work that into your EnterpriseCustomerVerificationServiceTest.
Is it possible to change the source code? if so maybe you could try to solve the problem without using any mocking framework at all.
see my comment on How To Java Unit Test a Complex Class

Can I test code that uses introspection with Mockito?

I'm writing unit tests for a block of code that uses introspection; specifically it calls getDeclaredField() on the class I want to mock and tries to get the value of the field. Is there a way to mock this with Mockito?
Mockito operates using the same introspection libraries you're trying to fool by creating a Mock. Even if you could cajole it to work, I'm not sure how easy it would be to understand or maintain.
I'd suggest creating a very small nested class and operating on it normally:
public class YourTest {
private static class SampleClass {
String field1;
int field2;
}
#Test public void introspectionWorks() {
yourSUT.process(new SampleClass());
}
}
Barring that, extract the difficult-to-mock call into a method you can stub easily:
public class YourSUT {
/* ... */
/* package */ Class<?> getFieldType(Object object, String fieldName) {
return object.getClass().getDeclaredField(fieldName).getType();
}
}
public class YourTest {
#Test public void introspectionWorks() {
YourSUT spy = Mockito.spy(yourSUT);
doReturn(String.class).when(spy).getFieldType(myObject, "someStringField");
}
}

Mockito bypass static method for testing

I need to test handleIn() method using Mockito.
However the code need to call this legacy code Util.getContextPDO which is a static method.
Note that in testing environment this Util.getContextPDO is always returns Exception, and I intend to bypass this Util.getContextPDO() by always return a dummy IPDO.
public class MyClass {
public IPDO getIPDO()
{
return Util.getContextPDO(); // note that Util.getContextPDO() is a static, not mockable.
}
public String handleIn(Object input) throws Throwable
{
String result = "";
IPDO pdo = getIPDO();
// some important business logic.
return result;
}
}
Initially I thought this achieveable by using spy() of the class "MyClass", so I can mock the return value of getIPDO(). Below is my initial effort using spy ()
#Test
public void testHandleIn() throws Exception
{
IPDO pdo = new PDODummy();
MyClass handler = new MyClass ();
MyClass handler2 = spy(handler);
when(handler2.getIPDO()).thenReturn(pdo);
PDOUtil.setPDO(pdo, LogicalFieldEnum.P_TX_CTGY, "test123");
IPDO pdoNew = handler2.getIPDO();
Assert.assertEquals("test123,(PDOUtil.getValueAsString(pdoNew, LogicalFieldEnum.P_TX_CTGY)));
}
However the when(handler2.getIPDO()).thenReturn(pdo); is throwing the Exception that I want to avoid ( because handler2.getIPDO() ) seems to call the real method.
Any idea on how to test this part of code?
A good technique for getting rid of static calls on 3rd party API is hiding the static call behind an interface.
Let's say you make this interface :
interface IPDOFacade {
IPDO getContextPDO();
}
and have a default implementation that simply calls the static method on the 3rd party API :
class IPDOFacadeImpl implements IPDOFacade {
#Override
public IPDO getContextPDO() {
return Util.getContextPDO();
}
}
Then it is simply a matter of injecting a dependency on the interface into MyClass and using the interface, rather than the 3rd party API directly :
public class MyClass {
private final IPDOFacade ipdoFacade;
public MyClass(IPDOFacade ipdoFacade) {
this.ipdoFacade = ipdoFacade;
}
private IPDO getIPDO() {
return ipdoFacade.getContextPDO();
}
public String handleIn(Object input) throws Throwable
{
String result = "";
IPDO pdo = getIPDO();
someImportantBusinessLogic(pdo);
return result;
}
...
}
In your unit test, you can then easily mock your own interface, stub it any way you like and inject it into the unit under test.
This
avoids the need to make private methods package private.
makes your tests more readable by avoiding partial mocking.
applies inversion of control.
decouples your application from a specific 3rd party library.
Changed my testing to :
#Test
public void testHandleIn() throws Exception
{
IPDO pdo = new PDODummy();
MyClass handler = new MyClass ();
MyClass handler2 = spy(handler);
doReturn(pdo ).when( handler2 ).getIPDO();
PDOUtil.setPDO(pdo, LogicalFieldEnum.P_TX_CTGY, "test123");
IPDO pdoNew = handler2.getIPDO();
Assert.assertEquals("test123,(PDOUtil.getValueAsString(pdoNew, LogicalFieldEnum.P_TX_CTGY)));
}
Solved after reading Effective Mockito.
when(handler2.getIPDO()).thenReturn(pdo);
Will actually call the method and then return pdo regardless.
Whereas:
doReturn(pdo).when(handler2).getIPDO();
Will return pdo without calling the getIPDO() method.

Categories

Resources