any(Classmember) returns null mockito - java

I am trying to do when().thenReturn() but facing issues. Following is the sample code that I came up with for SOers:
import java.util.List;
public class Sample {
public void function(List<SampleA> list) {
for (SampleA s : list) {
List<SampleB> nameList = s.v1;
for (SampleB m : nameList) {
SampleC value = m.getV2();
if (value != null) {
doSomething(value);
} else {
LOGGER.warn("No valid value");
}
}
}
}
}
public class SampleA{
List<SampleB> v1;
}
public class SampleB{
SampleC v2;
public SampleC getV2(){
return this.v2;
}
}
This might be silly but I just want to understand why can't I do:
SampleB sampleB = new SampleB();
when(sampleB.getV2()).thenReturn(any(SampleC.class));

I'm guessing that you are trying to test Sample.function and are trying to work out how to mock SampleC values. If so, then your code should probably look something like:
#Test
void testFunction() {
SampleC mockC = mock(SampleC.class);
SampleB mockB = mock(SampleB.class);
SampleA mockA = mock(SampleA.class);
when(mockB.getV2()).thenReturn(mockC);
when(mockA.getV1()).thenReturn(List.of(mockB));
Sample sample = new Sample();
sample.function(List.of(mockA));
// verify doSomething was called with mockC as its argument
when(mockB.getV2()).thenReturn(null);
sample.function(List.of(mockA));
// verify "No valid value" was logged
}
I've added a getV1 method rather than direct access to the field because my fingers refuse to write the code that directly accesses a public field :-)
If you're struggling with verifying that doSomething was called then that's where argument matching comes in. Ideally you'd have a SomethingDoer that you inject into your sample:
interface SomethingDoer {
void doSomething(SampleC sample);
}
class Sample {
private final SomethingDoer somethingDoer;
public Sample(SomethingDoer somethingDoer) {
this.somethingDoer = somethingDoer;
}
}
Then you'd add the following to your test:
SomethingDoer doer = mock(SomethingDoer.class);
Sample sample = new Sample(doer);
...
verify(doer).doSomething(mockC);
Also note that the code above is poor style: the tests should be split up with the setup code in a #BeforeEach method. I've just put it in a single test to keep the answer simple.

any(…) is an ArgumentMatcher. It is used to match arguments. You cannot use it to return instances of classes. What would "any SampleC" be?
You'd use it with mock objects, like so:
SampleInterface sample = Mockito.mock(SampleInterface.class);
when(sample.function(any(List.class))).thenReturn(new ArrayList<>());
// or: .thenAnswer(a -> new ArrayList<>()); to return a new instance for each call

you can't use ArgumentMatchers inside thenReturn or thenAnswer. You have to specify exactly what to return. For Example:
SampleB sampleB = mock(SampleB.class)
when(sampleB.getV2()).thenReturn(new SampleC());

Related

Skip method call in junit test case using EasyMock?

I am writing a test case for "headersection()" method. Inside this method, it is calling a constructor of another class, let's say "InformationHeader.java" class. Inside this constructor, it will invoke one method called as "makepage()". Again "makepage()" method will invoke another "createpage()" method.
I wanted to skip the method call to "createpage()" in my test case. Please suggest how to achieve this scenario?
private void headersection(Object child) {
headerobject = new InformationHeader(parameter_1, parameter_2, parameter_3, parameter_4);
//lines of code
}
//InformationHeader.java
public InformationHeader(parameter_1, parameter_2, parameter_3, parameter_4) {
//lines of code
makepage();
//lines of code
}
public final void makepage() {
//lines of code
createpage(); //I wanted to skip this method call
}
Any help would be appreciated
Thanks
I hope I got your question, but as I mentioned in my comment, you could change the method a bit and create a method which could be mocked.
void headersection(Object child) {
headerobject = getInformationHeader(/*parameter*/)
//lines of code
}
InformationHeader getInformationHeader(/*parameter*/) {
return new InformationHeader(parameter_1,parameter_2,parameter_3,parameter_4);
}
I don't know your class name in which the headersection mehtod is stored, lets say SectionService. Now, you could use Mockito to create a so called spy
#InjectMock
SectionService serviceToTest;
SectionService spyServiceToTest = Mockito.spy(serviceToTest);
InformationHeader spyInformationHeader = Mockit.spy(new InformationHeader(/*parameter*/));
Now you can mock a call inside of the tested class:
Mockito.doReturn(spyInformationHeader).when(spyServiceToTest).getInformationHeader(//parameter);
Mockiot.doNothing().when(spyInformationHeader).createpage();
Here is a stackoverflow question which is dealing with spy calls and
here is the Mockito documentation.
I hope this helps, greetings Matthias
The answer using spies doesn't work. The new InformationHeader(/*parameter*/) will call createpage. You will have the same problem with EasyMock.
The problem is that you can't mock a method before creating a partial mock. So when the constructor is calling a method, it doesn't work.
I would probably rethink my design if I was you. But not having the full picture, I can't give advice on that.
Keeping the current design, the easiest is actually to do a manual mock. It goes like this.
public class MyTest extends EasyMockSupport {
#Test
public void test() {
InformationHeader header = new InformationHeader("a", "b", "c", "d") {
#Override
public void createpage() {
// do nothing
}
};
ToTest toTest = partialMockBuilder(ToTest.class)
.withConstructor()
.addMockedMethod("createHeader")
.mock();
expect(toTest.createHeader()).andReturn(header);
replayAll();
toTest.headersection(null);
}
}
class ToTest {
void headersection(Object child) {
InformationHeader headerobject = createHeader();
}
InformationHeader createHeader() {
return new InformationHeader("a", "b", "c", "d");
}
}
class InformationHeader {
public InformationHeader(String p1, String p2, String p3, String p4) {
makepage();
}
public final void makepage() {
createpage();
}
public void createpage() {
throw new RuntimeException("Should not be called");
}
}

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

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.

How can I call a private method contained into a class that implements an interface, in a junit test?

edit: I apologize if the post has been considered too confusing, i'll edit it and leave only the parts regarding my problem...
I have written a class named "ArithmeticNode" which implements an interface containing the following methods:
public void turnOn() {
arithmeticServer.start();
}
public void turnOff(){
arithmeticServer.stop();
}
and contains also a private method:
private void negotiatePort(NodeManifest nodeManifest, ThriftServer arithmeticServer) {
while(true) {
int proposedPort = arithmeticServer.start();
int returnedPort = managementClient.registerNode(nodeManifest, proposedPort);
if(proposedPOrt != returnedPort) {
arithnemticServer.stop();
}
else
break;
}
}
What I'm trying to do is to write a test in which I create a number of these arithmetic nodes and make them register to a management node that I've already written and use as server. Then there will be a second part of my project where I'll make those nodes interact, but that's not part of the actual problem.
I have already written a working junit test:
#Test
public void testArithmeticServer() throws Exception {
List<NodeManifest> nodeManifests = new ArrayList<>();
nodeManifests.add(new NodeManifest("localhost", Arrays.asList(new String[]{"addition"})));
nodeManifests.add(new NodeManifest("localhost", Arrays.asList(new String[]{"subtraction","multiplication"})));
nodeManifests.add(new NodeManifest("localhost", Arrays.asList(new String[]{"addition","multiplication","division"})));
nodeManifests.add(new NodeManifest("localhost", Arrays.asList(new String[]{"addition","division"})));
List<ThriftServer> arithmeticServers = new ArrayList<>();
for (NodeManifest nodeManifest : nodeManifests) {
ThriftServer arithmeticServer = new ThriftServer(ArithmeticServiceHandler.class);
arithmeticServers.add(arithmeticServer);
negotiatePort(nodeManifest,arithmeticServer);
}
private void negotiatePort() {
while(true) {
int proposedPort = arithmeticServer.start();
int returnedPort = managementClient.registerNode(nodeManifest, proposedPort);
if(proposedPOrt != returnedPort) {
arithnemticServer.stop();
}
else
break;
}
}
I need to write a test where i don't have to put the negotiatePort method directly inside the test code, but I call for each node the private negotiatePort method I have inside my arithmeticNode class; I'm not sure if it's possible to do that and how. I hope I've been less confusing than the previous version of the post :-)
You can make the negotiatePort method package local. Then you would be able to call it within your test (which should reside in the same package). And nobody outside the package would be able to use it

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.

Testing Java class

I am testing Java app with JUnit. The following is the source code of a specific method:
public class Surgery {
Vector<Patient> patients;
String name;
public Surgery(String name) {
patients = new Vector<Patient>();
this.name = name;
}
public Patient findPatient(String name) {
Iterator<Patient> patientIt = patients.iterator();
while(patientIt.hasNext()) {
Patient next = patientIt.next();
if (next.getName().equals(name))
return next;
}
return null;
}
This is JUnit test method:
public class SurgeryTest {
private Vector<Patient> vector;
Surgery surgery_N =new Surgery("Teddy");
ByteArrayOutputStream ans = new ByteArrayOutputStream();
final String separator = System.getProperty("line.separator");
#Test
public void testFindPatient() {
surgery_N.findPatient("Teddy");
}
}
I need to test each statement in the source code method. I stuck, don't know what else to do. Any solution?
Your Surgery class contains no way to add patients to it from the code sample you have given us, so your unit test should be finding nothing.
To test each statement in the source code method you should create multiple tests that cover each one of the possible paths in your code. That means, in your tests you will want to test for the scenario where you return a patient name if it exists, and one for where the patient doesn't exist (returning null).
Here's some example methods for you to work from:
public void testFindPatientWherePatientExists() {
Patient thePatient = surgery.findPatient("Teddy");
assertEquals("Teddy", thePatient.getName());
}
public void testFindPatientWherePatientDoesntExist() {
assertNull(surgery.findPatient("I dont exist"));
}
What is the expected result when you call findPatient(...)? You can compare the expected result with the actual result using assertEqual(...)
public class SurgeryTest {
Surgery surgery;
#Before
public void setUp() {
surgery = new Surgery("Teddy");
}
#Test
public void testFindPatient() {
Patient p = ...; // expected result
assertEquals(p, surgery.findPatient("Teddy"));
}
}
The method with #Before annotation will be called before each method with #Test annotation. Therefore, the new surgery object is tested every time.
First, note that the name you pass to the Surgery constructor does NOT get placed into the patients Vector. It is a field of Surgery. Suggest you rename the arg to "surgeryName" and then you'll need a new method, addPatient(String patientName);, and call addPatient("Teddy").
That said, in general, you should test for both the name present and name absent case. e.g.
(exact name of the assert methods might vary)
assertNotNull(surgery.findPatient("Teddy"));
assertNull(surgery.findPatient("A Name I did not add"));
(first line would be more precise if it were assertEquals() like wannik suggested.

Categories

Resources