Junit And Mockito, Capturing method call on passed argument - java

I am relatively new to Mockito and Junit in Java. How can I capture or verify the interaction on the argument passed to function that I am testing.
Ex-- Main class
public class A{
public void setValues(Person p){
p.setFirstName('Lucky');
p.setLastName('Singh');
// Some more code
}
}
Test class
class Test {
#InjectMocks
A classUnderTest;
#Test
public void tests(){
classUnderTest.setValues(new Person());
// What to do next to verfiy that the setFirstName and setLastName where really called on Person Object as setValues have void return type??
}
}
Now i want to test this setValues method with void return type. I know if return type would have been Person I could have used assert. But I cannot change method defination.
So I want to verify that the call to setFirstName and setlastName is made.
I am using pit-test and the mutation removed call to setFirstName and setlastName is not getting KILLED.
How can I achieve this ??

You can inject a spy for your Person class and then verify if the methods are called as follows:
class Test {
#Spy
Person person = new Person();
#InjectMocks
A classUnderTest;
#Test
public void tests(){
classUnderTest.setValues(person);
// You can now verify if the methods setFirstName and setLastName where really called on Person
verify(person, times(1)).setFirstName(isA(String.class));
verify(person, times(1)).setLastName(isA(String.class));
}
}
A spy will wrap an existing instance, in your case Person. It will still behave in the same way as the normal instance, the only difference is that it will also be instrumented to track all the interactions with it so that you can actually verify on the methods that are called.

Related

How to cover the Class instantiated inside a method in Mockito Junit?

How can I cover the class instantiated inside a method and need to get the value that is not set.
Here is my Service class DemoClass.Java
public class DemoClass{
public void methodOne(){
ClassTwo classTwo=new ClassTwo();
classTwo.setName("abc");
customerRepo.save(classTwo);
ClassThree classThree=new ClassThree();
classThree.setId(classTwo.getId()); //here causing NullPointerException as ClassTwo is instantiated inside the method and the id value is not set and the test stops here.
classThree.setName("person1");
classThree.setUpdatedBy("person2");
}
}
As the classTwo is instantiated in the method level the test method does not get the getId(). And I can't change or add anything to the Controller class. The test stops at that line and causing NullPointerException as it doesn't know the value classtwo.getId() as it is not set. I need to cover that/ pass that line in the test class.
I tried mocking that class and spy also. Any Mockito solutions available for this.
The Id in ClassTwo is an autogenerated sequence number so no need of setting in DemoClass.Java
Here is my test class DemoClassTest.Java
#RunWith(MockitoJunitRunner.Silent.class)
public void DemoClassTest(){
#InjectMocks
DemoClass demoClass;
#Test
public void testMethodOne(){
demoClass.methodOne()
}
You could provide a customerRepo test double that just sets some specific id on classTwo:
public class TestCustomerRepo extends CustomerRepo {
public void save(ClassTwo classTwo) {
classTwo.setId(4711L);
}
}
But since you seem to be testing JPA code it would probably be a better idea to perform an integration test containing an actual database instead.
I usually do it like this:
long testId = 123;
Mockito.when(customerRepo.save(Mockito.any())).thenAnswer(invocation -> {
ClassTwo entity = (ClassTwo)invocation.getArgument(0);
entity.setId(testId);
return entity;
});
If you want to assert something on the ClassThree entity, do a Mockito.verify on the ClassThree repository mock.

Mockito doReturn if method of a object with certain class is called

If I have a object MyObject, I want to return some value if certain method of that object is called. For example something like this:
doReturn(someValue).when(Mockito.any(MyObject.class)).getSomeValue();
I have tried it like that, but it does not works :
org.mockito.exceptions.misusing.NullInsteadOfMockException:
Argument passed to when() is null!
You need to use Mockito.mock(MyObject.class) to create a mock of your object.
Currently you're using Mockito#any which is a parameter matcher used to define behavior on a mock when a stubbed method is called for any given parameter.
#Test
public void testMock() throws InterruptedException {
MyObject myObjectMock = Mockito.mock(MyObject.class);
doReturn(2).when(myObjectMock).getSomeValue();
System.out.println(myObjectMock.getSomeValue()); // prints 2
}
private class MyObject {
public int getSomeValue() {
return 1;
}
}
Alternatively, you can use Mockito annotations:
#RunWith(MockitoJUnitRunner.class)
public class YourTestClass {
#Mock
MyObject myObjectMock
saves you from manually mocking that object within your setup or test methods.

How do you mock classes that are used in a service that you're trying to unit test using JUnit + Mockito

I want to write a unit test for a service that uses/depends on another class. What i'd like to do is mock the behavior of the dependent class (As opposed to an instance of that class). The service method being tested uses the dependent class internally (i.e. an instance of the dependent class isn't passed in to the method call) So for example I have a service method that I want to test:
import DependentClass;
public class Service {
public void method() {
DependentClass object = new DependentClass();
object.someMethod();
}
}
And in my unit test of Service method(), I want to mock someMethod() on the DependentClass instance instead of having it use the real one. How do I go about setting that up in the unit test?
All of the examples and tutorials i've seen show mocking object instances that are passed in to the method being tested, but I haven't seen anything showing how to mock a class as opposed to an object instance.
Is that possible with Mockito (Surely it is)?
It's easy with Powermockito framework and whenNew(...) method. Example for your test as follows:
#Test
public void testMethod() throws Exception {
DependentClass dependentClass = PowerMockito.mock(DependentClass.class);
PowerMockito.whenNew(DependentClass.class).withNoArguments().thenReturn(dependentClass);
Service service = new Service();
service.method();
}
Hope it helps
This is a problem of poor design. You can always take in the param from a package private constructor.
Your code should be doing something like this:
public class Service {
DependentClass object;
public Service(){
this.object = new DependentClass();
}
Service(DependentClass object){ // use your mock implentation here. Note this is package private only.
object = object;
}
public void method() {
object.someMethod();
}
}

Mockito argument to a private method

This is my sample service class:
class Service {
#Inject
private TestDao dao;
public void method() {
//Other logic
List<SomeClass> list = new ArrayList<SomeClass>();
privateMethod(list);
//Other logic
}
private void privateMethod(List<SomeClass> list) {
dao.save(list);
}
}
If I mock dao using Mockito, then how can I test the number of calls to dao.save method? When I tried with verify, I have to give the list object. But I am not seeing any way to get that object.
Any thoughts?
You can use the anyList() matcher if you don't care about exactly what list your method is being called with. For example, if you want to verify the save() method was called exactly thrice:
verify(dao, times(3)).save(anyList())
If you want to make further assertions about what list save() was called with, use ArgumentCaptor
An example usage of ArgumentCaptor:
ArgumentCaptor<List> argument = ArgumentCaptor.forClass(List.class);
verify(dao, times(3)).save(argument.capture());
List secondValue = argument.getAllValues().get(1); // captured value when the method was called the second time
Call verify with Matchers.anyList():
verify(dao).save(Matchers.anyList());

mockito return sequence of objects on spy method

I know you can set several different objects to be be returned on a mock. Ex.
when(someObject.getObject()).thenReturn(object1,object2,object3);
Can you do the same thing with a spied object somehow? I tried the above on a spy with no luck. I read in the docs to use doReturn() on a spy like below
doReturn("foo").when(spy).get(0);
But deReturn() only accepts one parameter. I'd like to return different objects in a specific order on a spy. Is this possible?
I have a class like the following and i'm trying to test it. I want to test myClass, not anotherClass
public class myClass{
//class code that needs several instances of `anotherClass`
public anotherClass getObject(){
return new anotherClass();
}
}
You can chain doReturn() calls before when(), so this works (mockito 1.9.5):
private static class Meh
{
public String meh() { return "meh"; }
}
#Test
public void testMeh()
{
final Meh meh = spy(new Meh());
doReturn("foo").doReturn("bar").doCallRealMethod().when(meh).meh();
assertEquals("foo", meh.meh());
assertEquals("bar", meh.meh());
assertEquals("meh", meh.meh());
}
Also, I didn't know you could do when(x.y()).thenReturn(z1,z2), when I have to do this I use chained .thenReturn() calls as well:
when(x.y()).thenReturn(z1).thenThrow().thenReturn(z2)

Categories