Mock a DAO class and a method within it - java

I am trying to mock a DAO class that has a method which returns a list of a specific class.
private List<SpecificClass> getInfo(){
List<SpecificClass> returnInformation = dao.list(ParamOne, Param Two, SpecificClass.class);
}
The dao mentioned in the above method refers to another class.
I begin by mocking that DAO class.
Mockito.mock(TheDaoClass.class);
and creating a mocked list
private #Mock List<SpecificClass> returnedList = new ArrayList<SpecificClass>();
Then I make call to that method
dao.list(ParamOne, Param Two, SpecificClass.class);
and specify what needs to be done when it is called
when(dao.list(ParameterOne, anyString(), SpecificClass.class)).thenReturn(returnedList);
When I do the above I get a null pointer exception. There can be two causes:
I understand the list is empty but all it is supposed is hold SpecificClass's five values but that shouldn't throw an error at this point.
I think object dao is not getting mocked properly. I am only mocking the whole class Mockito.mock(TheDaoClass.class) in order to mock any object asociated with that class. I think that it is not achieving the objective. how do I go about solving this problem? Any help is appreciated. Thanks.

Make your mocked DAO object a property of your test class like so:
#Mock
private TheDaoClass mockDaoClass;
Then, in your setUp() method at the beginning of your test class call initMocks:
#BeforeClass
public void setUp() {
MockitoAnnotations.initMocks(this);
}
This should prevent the NullPointer.
Additionally, I recommend that rather than mock the List object (if you are mocking any Java library data type you are probably doing it wrong), you should create a list and populate it.
List<SpecificClass> list = new ArrayList<SpecificClass>();
list.add(new SpecificClass());
Then return the list from the mocked method.
when(mockDaoClass.list(anyString(), anyString(), SpecificClass.class)).thenReturn(list);

Related

Mockito not detecting call on repository of service when using doReturn instead of whenThen

I'm fairly new to Mocking, but I've read a lot, also took a course in udemy (not like I'm an expert, very far from it, just saying I've been studying this), but still, I cannot figure out something.
I have read this post Mockito - difference between doReturn() and when(), which made me understand a few things.
Now let me explain my problem.
I have a service impl class, that calls a repository class to get/do whatever I want. This service class is the one I'm writing my mockito's tests for.
This problem can be addressed in 2 different ways.
First way: (when thenReturn)
I have my test class which looks something like this (pseudo code):
serviceImplCastTest {
#Spy
#InjectMocks
ServiceImplClass serviceImplClass;
#Mock
RepositoryClass repositoryClass;
#Test
void whenMethodInService_thenReturnNonEmptyMap() {
List<Class> classList = new ArrayList<~>();
Class class = new Class("Whatever");
classList.Add(class)
Map<String, Class> classMap = classList.stream.collect(Collectors.toMap(Class::getMethod, Function.identity()));
when(serviceImplClass.methodInService()).thenReturn(classMap);
Map<String, Class> actualMap = serviceImplClass.methodInService();
assertFalse(actualMap.isEmpty());
verify(repositoryClass, times(1)).methodInRepository();
}
So, this doesn't work because the method in the service, which returns a map, calls a method in the repository that returns a List of Class and then my method in the service turns that list into a map, and for some reason, Mockito is expecting a List of Class, instead of a Map. I get the Mockito wrong type of return error.
(This code works perfectly if the service method just returns the same type of List that the repository returns.)
Second way: (doReturn when)
serviceImplCastTest {
#Spy
#InjectMocks
ServiceImplClass serviceImplClass;
#Mock
RepositoryClass repositoryClass;
#Test
void whenMethodInService_thenReturnNonEmptyMap() {
List<Class> classList = new ArrayList<~>();
Class class = new Class("Whatever");
classList.Add(class)
Map<String, Class> classMap = classList.stream.collect(Collectors.toMap(Class::getMethod, Function.identity()));
doReturn(classMap).when(serviceImplClass).methodInService();
Map<String, Class> actualMap = serviceImplClass.methodInService();
assertFalse(actualMap.isEmpty());
verify(repositoryClass, times(1)).methodInRepository();
}
Now, when using doReturn when, everything works fine, except the verify, repositoryClass.methodInRepository() doesn't get called, or at least is not spied properly or something, Mockito throws error "Wanted but not invoked".
So I'm not sure how to fix this on the Mockito side, because a simple way is to change logic, service return list instead of map, then change my application to receive list and map it over there, but this implies affecting logic, which I was forbidden to do so.
Also and I'm honestly interested on being able to mock this, because I have a few other equivalent cases, where my service class processes the list then turns it into something else, and mocking still expects a list to be returned.
How can I mock this? What is the correct approach?
You are making the same mistake in both of your code snippets, in that you're stubbing a method in the class that you're trying to test, instead of stubbing the method in the mocked class.
This means that you're effectively just testing the stubbing, not testing the class itself.
What you want to do is
Get rid of the Spy annotation - you don't need a spy for this.
Stub the method of the repository class, not the service class.
That way, you'll be testing that the service class calls the repository class correctly, and handles the response from the repository class correctly. But you'll also be circumventing the implementation of the repository class, which is the whole point of using a mock.

How to inject mock collection by annotation with Mockito

I have create one parameterized class that takes two params. One is type of string and another is type of List of Abstract class. Class constructor looks like below code.
public TestService(Tenant tenant, List<AbstractService> testServices) {
testServicesMap = testServices.stream().collect(Collectors.toMap(AbstractService::getType, Function.identity()));
}
now I want to write Junit test case for this class and for that I have following piece of code.
#Mock
protected Tenant tenant;
#Mock
private List<AbstractService> testServices;
#InjectMocks
private TestService testService;
#Before
public void setup() {
testServices.add(new JobService(new JobEventService()));
testServices.add(new ApplicationService(new ApplicationEventService()));
testServices.add(new UserService(new UserEventService()));
// notificationService = new NotificationService(tenant, notificationServices);
// MockitoAnnotations.initMocks(notificationService);
}
I also tried to enabled two commented lines but its now working. Following is error that system throw on start.
org.mockito.exceptions.base.MockitoException:
Cannot instantiate #InjectMocks field named 'notificationService' of type 'class com.test.TestService'.
You haven't provided the instance at field declaration so I tried to construct the instance.
However the constructor or the initialization block threw an exception : `null`.
Could someone help on this ?
you are mixing mocks with real objects, because you create a mock of list but then call add method on that list and then you expect stream() to work as usually.
Mockito mocks don't do anything by default so you have to tell it:
Mockito.when(testServices.stream())
.thenReturn(Stream.of(new JobService(new JobEventService())));
or better in your case is to remove #Mock from testServices and assign it a new ArrayList
The problem is that you try to mock the list, and list.stream() is called, which in the mock default returns null.
A common solution from the duplicate questions is to use a #Spy of the list.

How can I create fake data and the data object for unit testing?

I have a class that implements a cache and I want to write a JUnit test for it.
The class implements and interface with methods like:
public void insert(Object key, Object value);
public Object getFromCache(Object key);
and the basic implementation is a singleton.
I am writing a JUnit test but I don't know how to properly create a dummy cache with data in order to use for testing.
Right now I am doing:
#Test
public void myTest() {
MyCache cache = MyCache.getInstance();
populateWithData(cache);
//test cache
asserEquals etc
}
How can I avoid using the getInstance() and not populate on each test?
Apparently I slightly misread your question.
As the other two answers state, if you want to have a specific cache which you can read from when running each testcase, you could use a ´#before´ method, which initializes your object to be used in your testcase. Each ´#before´ method defined is called prior to calling each testcase. This means that you can write the code to instantiate the object once instead of many times.
Note that if you want to do something different in a testcase, consider adding the customization at the top of that, instead of edition your #before method, since that will impact all your testcases.
Just for clarity's sake, I will include some code:
MyCache cache = null;
#before
public void initCache(){
cache = MyCache.getInstance();
populateWithData(cache);
}
// ... rest of your program here ...
Original answer:
You can use this if you want to do more fancy testing of more complicated objects. This can still be used in conjunction with the ´#before´ annotation
You could try mockito...
This is basically a framework to mock off a function or class, that you are not interested in implementing in its totally, especially for testing.
Here is a sample using a mocked off list:
import static org.mockito.Mockito.*;
// mock creation
List mockedList = mock(List.class);
// using mock object - it does not throw any "unexpected interaction" exception
mockedList.add("one");
mockedList.clear();
// selective, explicit, highly readable verification
verify(mockedList).add("one");
verify(mockedList).clear();
// you can mock concrete classes, not only interfaces
LinkedList mockedList = mock(LinkedList.class);
// stubbing appears before the actual execution
when(mockedList.get(0)).thenReturn("first");
// the following prints "first"
System.out.println(mockedList.get(0));
// the following prints "null" because get(999) was not stubbed
System.out.println(mockedList.get(999));
You can basically tell mockito which functions you expect to call on the object, and what you expect the result to be... very versatile. I expect that it will fulfill your needs.
'Reset' singleton before each test. More details can be found here.
For example:
#Before
public void resetMyCacheSingleton() throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
Field instance = MyCache.class.getDeclaredField("instance");
instance.setAccessible(true);
instance.set(null, null);
}
You can use #BeforeClass annotation to do something which will be common and may be computational expensive stuff.
This will ran only once before all the testcases.
#BeforeClass
public static void myTest() {
MyCache cache = MyCache.getInstance();
populateWithData(cache);
//test cache
asserEquals etc
}
P.S. Since #BeforeClass can be used with static method only, populateWithData() needs to be static as well. and since populateWithData() method is static, variables used inside it must be static as well.
You can also check #AfterClass to clean/reset some data/resources.

How do I test a void method using JUnit and Mockito?

My void method changes boolean variable value in the class. How do DI check that?
I have:
mocked class object
called the method with proper parameters
checked the instance variable
But that doesn't change the value of instance variable. How do I do this?
ReferenceLettersBean rf = Mockito.mock(ReferenceLettersBean.class);
rf.setBoolcheck(false);
Mockito.doNothing().when(rf).checkForDuplicates(anyString(), anyString(), anyString());
rf.checkForDuplicates("abcd#emal.com","abd#gmail.com","abcd#gmail.com");
assertEquals(true,rf.getBoolcheck());
DON'T mock the class you are trying to test.
DO mock the classes that interact with the class you are trying to test.
If you want to test that a field in a a class changes from false to true, what you really want to do is something like (I don't have your actual constructor, I'm just guessing):
SomeDependency dependency = mock(SomeDependency.class);
// Make a REAL ReferenceLettersBean
ReferenceLettersBean bean = new ReferenceLettersBean(dependency);
// now make your test
rf.checkForDuplicates("abcd#emal.com","abd#gmail.com","abcd#gmail.com");
assertEquals(true,rf.getBoolcheck());
This boolean value seems to be an internal state. This is not something you can directly test with unit tests unless you make it public or it is detectable by influencing the behavior of another method.

How to mock static methods using UnitilsJUnit4?

I have method getAllCustomers inside CustomerService class. Inside this method I call another static method from CustomerDao class.
Now when I am writing the junit for method getAllCustomers inside customerService class, where I want to mock the call to
static method of CustomerDao i.e. getAllCustomers. Here is the brief code snippet of method getAllCustomers inside
CustomerService class. Is it possible to mock the static method call using unitils?
Public static List<CustomerDate> getAllCustomers()
{
//some operations
List<CustomerDate> customers=CustomerDao.getAllCustomers();// static method inside CustomerDao
//some operations
}
Above code is just an example I am trying to put. Please avoid the discussion why these methods are designed as static
methods. That's a separate story .)
I doubt whether it can be achieved with unitils.
But please consider using PowerMock instead which seems to be capable of handling what you need. It can mock static methods,private methods and more (Ref: PowerMock)
This would be a matter of:
Setting up the mock
Calling the mock and expecting some data back
Verifying the end result of your call given your data
So, without really much ado about the static call, here's the way you can set it up in PowerMock:
#RunWith(PowerMockRunner.class)
#PrepareForTest(CustomerDao.class)
public class CustomerTest {
#Test
public void testCustomerDao() {
PowerMock.mockStatic(CustomerDao.class);
List<CustomerDate> expected = new ArrayList<CustomerDate>();
// place a given data value into your list to be asserted on later
expect(CustomerDao.getAllCustomers()).andReturn(expected);
replay(CustomerDao.class);
// call your method from here
verify(CustomerDao.class);
// assert expected results here
}
}

Categories

Resources