How to mock a void method with Functional Interface/lambda param? - java

How do I mock a lambda expression that is passed as a param into a void method call?
I have the following class structure that I need to test, but I can't even instantiate it due to it's constructor.
Is there a way to mock the method call someManager.doSomething?
Or a way to mock item.isDoItemSave?
I can't figure it out and SomeClass.setDoSave throws a null pointer on the return call(SomeClass line 18) , since doSave is null.
Class I want to instantiate:
public SomeClass() {
private Boolean doSave;
private SomeManager someManager;
private SaveAction action;
public SomeClass(SomeManager someManager) {
this.someManager = someManager;
action = setDoSave() ? SAVE : null;
}
private boolean setDoSave() {
if(doSave == null) {
someManager.doSomething(item -> {
doSave = item.isDoItemSave();
});
}
return doSave;
}
}
SomeManager.doSomething is void:
public void doSomething(ItemUpdate update){
Item item = new Item();
update.update(item);
}
ItemUpdate is a functional interface:
#FunctionalInterface
public interface ItemUpdate {
void update(Item item);
}
I cannot refactor this constructor, who knows what will happen, the code is extremely coupled.
I just want to be able to instantiate SomeClass.
My test class looks like this, naturally tests fail in the #BeforeEach on SomeClass constructor call:
class SomeClassTest {
private SomeClass someClass;
#Mock
private SomeManager someManagerMock;
#BeforeEach
void setUp() {
MockitoAnnotations.initMocks(this);
this.someClass = new SomeClass(someManagerMock);
}
#Test
void someClassTest() {
someClass.anyOtherMethod();
}
}

A quick glance at the documentation shows the following example that I have applied to your situation
#BeforeEach
void setUp() {
MockitoAnnotations.initMocks(this);
//configure the mock
// Java 8 - style 2 - assuming static import of AdditionalAnswers
doAnswer(answerVoid(ItemUpdate update) -> {
Item item = new Item();
//...populate item as needed
update.update(item);
})
.when(someManagerMock).doSomething(any(ItemUpdate.class));
this.someClass = new SomeClass(someManagerMock);
}
Reference Java 8 Custom Answer Support
Note that I have not tested this. I am going based on what was shown in the docs.

For now I have made changes so SomeClass at least instantiates.
Lesson learned, watch your assignments from Boolean to boolean.
private boolean setDoSave() {
if(doSave == null) {
someManager.doSomething(item -> {
doSave = item.isDoItemSave();
});
}
return doSave != null ? doSave : false;
}
I'm leaving this question open hoping someone with better knowledge of Mocking frameworks can provide a way of mocking this case.

I can't figure it out and SomeClass.setDoSave throws a null pointer,
since doSave is null.
SomeClass.setDoSave throws NPE since instance variable someManager is null.
Try adding #RunWith(MockitoJUnitRunner.class) to your test class.

Related

Java MockedStatic method is still called

So I'm using MockedStatic<> to mock a static method but it seems like the item inside is still getting called? If this is the case, what's the point of mocking it? I have the following setup:
Object being tested:
public class ObjectBeingTested {
public void methodBeingTested() {
Object obj = ObjectInQuestion.getInstance(new Object(), "abc");
// do stuff with obj
}
}
The object with static method:
public class ObjectInQuestion {
public static ObjectInQuestion getInstance(Object obj, String blah) {
someLocalVar = new FileRequiredObject();
// we get NullPointerException here cuz in test env, no files found
}
private ObjectInQuestion() {
// private constructor to make people use getInstance
}
}
Test code:
public class MyTestClass {
MockedStatic<SomeClass> mySomeClass;
#Mock ObjectInQuestion mMockedObjectInQuestion;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
mySomeClass = mockStatic(SomeClass.class);
when(SomeClass.getInstance(any(), anyString()).thenReturn(mMockedObjectInQuestion);
}
#After
public void tearDown() {
mySomeClass.close();
}
}
My questions are the following:
Why calling ObjectInQuestion.getInstance() in the test class, it's totally fine but when it's being called from ObjectBeingTested, it runs the real construction?
I tried to use mockConstruction on FileRequiredObject, it still actually construct the object ... why?
You're using the wrong syntax for stubbing the static method. You want something like
mySomeClass.when(
()->SomeClass.getInstance(any(), anyString()))
.thenReturn(mMockedObjectInQuestion);
More information available here
Assuming MockedStatic<SomeClass> mySomeClass; is actually MockedStatic<ObjectInQuestion> mySomeClass;, I would try to simplify the setup using a classic try block.
In any case, sharing the actual test method might be able to shine some light. ;)

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);
}
}

Mock inherited method in Mockito Java

My class structure is as follows:
public class MyParentClass {
void doSomethingParent() {
System.out.println("something in parent");
}
}
public class MyClass extends MyParentClass {
protected String createDummyRequest(Holder myHolder) {
//...
super.doSomethingParent();//I want to avoid this
//...
callingDB();
return "processedOutput";
}
private void callingDB() {
System.out.println("Calling to DB");
}
}
Then my unit test:
public class UnitTest {
public void testCreateDummyRequest() {
//create my mock holder
Holder mockHolder = new Holder();
MyClass mockObj = Mockito.mock(MyClass.class);
//mock doSomethingParent()
//mock callingDB()
//as mockObj is a fully mock, but I need to run my real method
//Mockito.when(mockObj.createDummyRequest(mockHolder)).thenCallRealMethod();
mockObj.createDummyRequest(mockHolder);
//Problem: doSomethingParent() is getting called though I have mocked it
}
}
How do I prevent the calling of the super.doSomethingParent() in my method? (method which I am writing my test)
With this class structure mocking and testing is real hard. If possible, I'd advice to change the structure as in mist cases a class structure that's hard to mock and test is equally hard to extend and maintain.
So if you could change your class structure to something similar to:
public class MyClass {
private DoSomethingProvider doSomethingProvider;
private DbConnector dbConnector;
public MyClass (DoSomethingProvider p, DbConnector c) {
doSomethingProvicer = p;
dbConnector = c;
}
protected String createDummyRequest(Holder myHolder){
//...
doSomethingProvider.doSomethingParent();
//...
dbConnector.callingDB();
return "processedOutput";
}
}
Then you could easily create your instance with mocks of DoSomethingProvider and DbConnector and voila....
If you can't change your class structure you need to use Mockito.spy instead of Mockito.mock to stub specific method calls but use the real object.
public void testCreateDummyRequest(){
//create my mock holder
Holder mockHolder = new Holder();
MyClass mockObj = Mockito.spy(new MyClass());
Mockito.doNothing().when(mockObj).doSomething();
mockObj.createDummyRequest(mockHolder);
}
Note: Using the super keyword prevents Mockito from stubbing that method call. I don't know if there is a way to stub calls to super. If possible (as in you didn't override the parent method in your class), just ommit the keyword.
I faced similar issue, so I find out that using spy() can hepld.
public class UnitTest {
private MyClass myObj;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
myObj= spy(new MyClass());
}
#Test
public void mockedSuperClassMethod(){
doNothing().when((MyParentClass )myObj).doSomethingParent();
//...
}
}
This approach works for me.
I found another approach, which turned out to be very useful in my case.
In the case I had, I needed to create a new class extending another, which included a very complex (legacy code) protected final method. Due to the complexity, it wasn't really possible to refactor to use composition, so here's what I came up with.
Let's say I have the following:
abstract class Parent {
public abstract void implementMe();
protected final void doComplexStuff( /* a long parameter list */) {
// very complex legacy logic
}
}
class MyNewClass extends Parent {
#Override
public void implementMe() {
// custom stuff
doComplexStuff(/* a long parameter list */); // calling the parent
// some more custom stuff
}
}
Here's how I rearranged this code:
abstract class Parent {
public abstract void implementMe();
protected final void doComplexStuff( /* a long parameter list */) {
// very complex legacy logic
}
}
interface ComplexStuffExecutor {
void executeComplexStuff(/* a long parameter list, matching the one from doComplexStuff */);
}
class MyNewClass extends Parent {
private final ComplexStuffExecutor complexStuffExecutor;
MyNewClass() {
this.complexStuffExecutor = this::doComplexStuff;
}
MyNewClass(ComplexStuffExecutor complexStuffExecutor) {
this.complexStuffExecutor = complexStuffExecutor;
}
#Override
public void implementMe() {
// custom stuff
complexStuffExecutor.doComplexStuff(/* a long parameter list */); // either calling the parent or the injected ComplexStuffExecutor
// some more custom stuff
}
}
When creating instance of MyNewClass for "production" purposes, I can use the default constructor.
When writing unit tests, however, I'd use the constructor, where I can inject ComplexStuffExecutor, provide a mock there and only test my custom logic from MyNewClass, i.e.:
class MyNewClassTest {
#Test
void testImplementMe() {
ComplexStuffExecutor complexStuffExecutor = Mockito.mock(ComplexStuffExecutor.class);
doNothing().when(complexStuffExecutor).executeComplexStuff(/* expected parameters */);
MyNewClass systemUnderTest = new MyNewClass(complexStuffExecutor);
// perform tests
}
}
At first glance, it seems like adding some boilerplate code just to make the code testable. However, I can also see it as an indicator of how the code should actually look like. Perhaps one day someone (who would find courage and budget ;) ) could refactor the code e.g. to implement the ComplexStuffExecutor with the logic from doComplexStuff from Parent, inject it into MyNewClass and get rid of inheritance.
Here is how it can be done
public class BaseController {
public void method() {
validate(); // I don't want to run this!
}
}
public class JDrivenController extends BaseController {
public void method(){
super.method()
load(); // I only want to test this!
}
}
#Test
public void testSave() {
JDrivenController spy = Mockito.spy(new JDrivenController());
// Prevent/stub logic in super.method()
Mockito.doNothing().when((BaseController)spy).validate();
// When
spy.method();
// Then
verify(spy).load();
}
Source: https://blog.jdriven.com/2013/05/mock-superclass-method-with-mockito/

EasyMock mocked method call is returning null when called for the second time after resetting mock object

This is my first post in Stackoverflow, so far I have been the active reader of this forum and I am posting my first question here.
This is regarding the EasyMock usage, I am a new user of EasyMock and in the following example code I am setting expectation for a collaborator method with the same object to be returned (doesn't matter whether it is same object or different object but the result is same) and I am resetting before going out of the test method. but when the second test is executed, the mocked method is returning null, I am not sure why is this happening.
If I run the methods
#RunWith(PowerMockRunner.class)
#PrepareForTest({CollaboratorWithMethod.class, ClassTobeTested.class})
public class TestClassTobeTested {
private TestId testId = new TestId();
#Test
public void testMethodtoBeTested() throws Exception{
CollaboratorWithMethod mockCollaborator = EasyMock.createMock(CollaboratorWithMethod.class);
PowerMock.expectNew(CollaboratorWithMethod.class).andReturn(mockCollaborator);
EasyMock.expect(mockCollaborator.testMethod("test")).andReturn(testId);
PowerMock.replay(CollaboratorWithMethod.class);
EasyMock.replay(mockCollaborator);
ClassTobeTested testObj = new ClassTobeTested();
try {
testObj.methodToBeTested();
} finally {
EasyMock.reset(mockCollaborator);
PowerMock.reset(CollaboratorWithMethod.class);
}
}
#Test
public void testMothedtoBeTestWithException() throws Exception {
CollaboratorWithMethod mockCollaborator = EasyMock.createMock(CollaboratorWithMethod.class);
PowerMock.expectNew(CollaboratorWithMethod.class).andReturn(mockCollaborator);
EasyMock.expect(mockCollaborator.testMethod("test")).andReturn(testId);
PowerMock.replay(CollaboratorWithMethod.class);
EasyMock.replay(mockCollaborator);
ClassTobeTested testObj = new ClassTobeTested();
try {
testObj.methodToBeTested();
} finally {
EasyMock.reset(mockCollaborator);
PowerMock.reset(CollaboratorWithMethod.class);
}
}
}
Here is my Collaborator class
public class CollaboratorWithMethod {
public TestId testMethod(String text) throws IllegalStateException {
if (text != null) {
return new TestId();
} else {
throw new IllegalStateException();
}
}
}
And here is my class under test
public class ClassTobeTested {
public static final CollaboratorWithMethod collaborator = new CollaboratorWithMethod();
public void methodToBeTested () throws IOException{
try {
TestId testid = collaborator.testMethod("test");
System.out.println("Testid returned "+ testid);
} catch (IllegalStateException e) {
throw new IOException();
}
}
}
I am looking for help from you guys to understand what exactly is happening here
The collaborator variable in class ClassTobeTested is final. The first test case initalizes the variable with mock object. The second test case cannot initialize the variable again. You set the expectation on the mock object created in second test case but actually the variable is still referring to the first mocked object.
Since you do not want to modify the class, you should set the mock reference once using #BeforeClass and make "mockCollaborator" a global variable so that you can use the reference in multiple test cases.

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