Mockito issue with List - java

I have a DAO method which returns a List.
Now I am trying to mock this DAO class in my service layer but when I invoke the DAO method, it is giving me a empty even though I have mocked the DAO method
Below is the sample code snippet,
public class ABCTest {
#InjectMocks
ABC abc = new ABC();
#Mock
private ABCDao dao;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
dao = Mockito.mock(ABCDao.class);
Mockito.when(dao.getListFromDB()).thenReturn(Arrays.asList("1","2","3"));
}
#Test
public void testServiceMethod() {
abc.serviceMethod(); // Inside this method when the DAO method is called, it is giving me an empty list even though I have mocked it above.
}
Any pointers would be helpful

Don't use MockitoAnnotations.initMocks(this); use #RunWith(MockitoJunitRunner.class) instead
You are calling dao = Mockito.mock(ABCDao.class) which overrides the dao created by MockitoAnnotations.initMocks(this)
the ABCDao instance inside ABC is now different to the dao member of your test case.
I can only assume that the following would fail:
assertTrue(dao == abc.getDao())
Solution: Remove the following line
dao = Mockito.mock(ABCDao.class);

Related

Spring injecting an initiallized mock via constructor

I have a singleton class (so private constructor) which needs to use a Spring Data repository during initialization. I have one injected as a constructor argument. Roughly:
#Controller
public class MyClass {
#Autowired
private MyClass(MyRepository repo) {
repo.findAll();
}
}
I want to unit test my class, so I need to have a mock repository initialized with mock values and then passed into my class before my class is initialized. How do I write my Mockito mocks in my JUnit test to make this possible?
You don't need Spring; this is an advantage of constructor injection. Just use MyRepository mockRepo = mock(MyRepository.class) and new MyClass(mockRepo).
(Your constructor should be public, by the way. You seem to be making the common mistake of confusing different senses of "singleton"; in the case of DI it simply means that the container only makes a single instance and shares it. Finally, if you only have one constructor you don't need #Autowired.)
Unit test should be independent. It means, we are not using real data from database even call any service from our test file.
Assuming you are using JUni5 and have findAllStudents() in your controller. So your test file approximately like this
#TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class MyClassTest {
#Mock
private MyRepository repo;
#InjectMocks
private MyClass controller;
#BeforeAll
public void setup() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testDataIsExist() {
List<String> expectednames = new ArrayList();
expectedNames.add("Foo");
expectedNames.add("Bar");
Mockito.when(myRepo.findAll()).thenReturn(expectedNames);
List<String> result = controller.findAllStudents();
Assertions.assertNotNull(result);
Assertions.assertEquals(expectednames, result);
}
}
So we are mock all the services we use in controller, then inject to controller itself. Then inside the test method we mock repo.findAll() to return expectedNames so if the controller find that function it will return what mock says to return.
After we call the function, we have to make it sure that the result is according to what we expected.
There is little value in a "unit test" for a #Controller implementation. If you use #WebMvcTest, then you can use #MockBean:
#WebMvcTest
class MyControllerTest {
#Autowired
private MockMvc mockMvc;
#MockBean
private MyRepository repository;
#Test
void testSomething() {
mockMvc.perform( ... );
}
}

Unit testing a method of a class that has a constructor and an autowired field that needs to be mocked using mockito

I have a service class that extends another service with a constructor. This class has an autowired field and a method that I wanted to unit test using Mockito. However, I am having trouble writing a unit for it.
Let say the service looks somewhat like this:
#Service
public class SomeService extends Service {
#Autowired
private SomeClient someClient;
public SomeService(Product product, #Qualifier(Constants.SOME_BEAN) Details temp) {
super(product, temp);
}
#Override
public State create() {
Request request = new Request();
request.set...
request.set..
Status status = someClient.createTenant(request);
..
.. // construct a State object and return
}
}
Now, I am writing a test for this class and I am trying to unit test the method create() above. I am having trouble mocking someClient there when this method is called by my test.
The test class looks somewhat like:
#RunWith(MockitoJUnitRunner.class)
public class SomeServiceTest {
private Detail temp;
private SomeFacade service;
private SomeClient someClient;
private Product product;
#Before
public void setup() {
temp = mock(Details.class);
product = mock(Product.class);
service = spy(new SomeService(product, temp));
someClient = mock(SomeClient.class);
}
#Test
public void test() {
Status status = new Status();
status.setStatus(...);
when(someClient.createTenant(any())).thenReturn(status);
State state = service.create();
// asserts
}
}
What I want to is that when I call service.create in the test above, the call
someClient.createTenant(request); in the method tested should be mocked to return a value and this is something I am not able to get working. Any help?
We can use Mockito's #InjectMocks-annotation to inject mocks into our unit under test. For this, we also need to
remove mock intialization from the setup()-method and
annotate the mocks with #Mock
Remarks:
Instead of field injection, I would recommend constructor injection. This allows, among other things, to keep the structure of the code and create the unit under test within setup() by manual injection
I would also recommend to add a type to the when: when(someClient.createTennant(any(Request.class)))...
As was pointed out by #second, the spy on the unit under test is superfluous.
Also pointed out by #second was the fact that field injection will not work if a constructor is present

unit testing a method called from another class

I am new to Android unit testing and I am using Mockito to do it.
I want to test my method which has a method from another class. I want to stub that method so that it should not be called. I am using doReturn().when() so that original method is not called but it is calling the original method.
Here is my code:
doReturn(true).when(myclass1mock).methodofclass1();
boolean a = myclass1mock.methodofclass1(); //here it return true
class2spy.methodofclass2(anyvalue);
The method I am testing is:
public class2 {
public void methodofclass2(Value) {
boolean value = class1.methodofclass1(); //here I don't want to call this method
}
}
The problem is method of class1 is called everytime. I want something so that class1.methodofclass1() is not called.
I am injecting using:
#Mock
class1 myclass1mock;
#InjectMocks
class2 myclass2;
#Before
public void setUp() {
myclass2 = new myclass2();
class2spy = Mockito.spy(myclass2);
}
As you want to test the behavior of Class2, then i think you mixed up the annotations. Also i would take advantage of #Spy annotations rather that configuring it by hand:
#Spy
class1 myclass1Spy;
#InjectMocks
class2 myclass2;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
Also, do not try not to spy the class which is being under test (class2). Use the real implementation.

PowerMockito using InjectMocks error

I have a very complicated class to write Junit test case. I decided to use PowerMockito since my class for which the test is to be run has a constructor initialization.
My main class is like this:
public class MainClass extends BaseClass{
MainClass(SomeClass class){
super(class);
}
public void methodToBeTested(){
some code here
}
..few other methods which I am not going to test.
}
Now I have the test case written like this:
#RunWith(PowerMockRunner.class)
public class TestClass{
#Mock
OtherClassUsedInMainClass mock1;
#Mock
OtherClassUsedInMainClass mock2;
#InjectMocks
MainClass mainClass;
#Before
public void setUp() throws Exception{
MockitoAnnotations.initMocks(this);
PowerMockito.whenNew(MainClass.class).withArguments(Mockito.any(SomeClass.class))
.thenReturn(mainClass);)
}
#Test
public void testMethodtobeTested(){
...I am using the other objects to mock data and test if this method works fine
mainClass.methodtobeTested();
\\This method will increment a value. I am just asserting if that value is right.
Assert.assertEquals(mainClass.checkCount(),RequiredCount)
}
}
I am getting a null pointer exception when running the Testcase since it tries to initialize the mainClass. It does not get mocked. I know I am doing something wrong. But I just don't know what it is.
Error:
org.mockito.exceptions.base.MockitoException:
Cannot instantiate #InjectMocks field named 'mainClass' of type 'class com.main.MainClass'.
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
Caused by: java.lang.NullPointerException
This null pointer exception is thrown from a the constructor of the BaseClass when it tries to initialize another class.
This question explains the difference between #Mock and #InjectMocks:
#Mock creates a mock. #InjectMocks creates an instance of the class and injects the mocks that are created with the #Mock (or #Spy) annotations into this instance.
MainClass constructor expects a SomeClass parameter but there isn't any mock for that.
Your code should be something like:
#RunWith(PowerMockRunner.class)
public class TestClass{
#Mock(answer = Answers.RETURNS_DEEP_STUBS)
SomeClass mock1;
#InjectMocks
MainClass mainClass;
#Before
public void setUp() throws Exception{
...
Quoting this answer, which is quoting the #InjectMocks documentation:
Constructor injection; the biggest constructor is chosen, then arguments are resolved with mocks declared in the test only. Note: If arguments can not be found, then null is passed.
So, presumably, declare a field of type SomeClass, and annotate it #Mock.
If you can't show us the actual code it is very hard to guess what exactly is happening. But it looks like your mock SomeClass needs some stubbed behavior to satisfy the BaseClass constructor.
For example:
// the instance of MainClass you run your tests against
private MainClass instance;
#Mock
private SomeClass someClass;
#Mock
private SomethingElse somethingElse;
#Before
public void setUp() {
when(someClass.doSomething()).thenReturn(somethingElse);
instance = new MainClass(someClass);
}
#Test
public void test() {
// SETUP
when(somethingElse.doWeirdStuff()).thenThrow(new WeirdException());
// CALL
instance.performTapDance();
// VERIFY
assertTrue(instance.isWeird());
}

Doubts with mockito

I have a doubt with Mockito.
I would want to test this simple class:
public class MyClass{
private UserService userService;
public void deleteUser(){
userService.getAdminUser(1);
userService.deleteUser(0);
}
}
I wrote this simple test:
#RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
#MockitoAnnotations.Mock
private UserService userService;
#Test
public void test(){
MyClass myClass=new MyClass();
myClass.userService=userService;
myClass.deleteUser();
}
}
This test run with no errors.
I await that it didn't compile because there isn't any call to userService method..
Mocks created by Mockito are "smart". They don't do anything when a void method is called. They return null when a method returning an object is called. They return an empty collection when a method returning a collection is called.
If you want to verify that getAdminUser() and deleteUser() have been called, use Mockito.verify().
These two things are explained in the Mockito documentation, points 1 and 2. In particular:
By default, for all methods that return value, mock returns null, an empty collection or appropriate primitive/primitive wrapper value (e.g: 0, false, ... for int/Integer, boolean/Boolean, ...).
you have not added any check to see if userService is used in any way. Adding a verify will do that for you: When to use Mockito.verify()?
I would advice you to read up on how Mockito works in tests, I think you have jumped past some of the fundamentals when it comes to learning the design and how method calls to the mock is treated.
Here is how you would test it with a different set of methods which invokes no annotations. Note that this is TestNG, but adapting it to JUnit 4+ is easy:
import static org.mockito.Mockito.*;
public final class Test
{
private UserService userService;
#BeforeMethod
public void init()
{
userService = mock(UserService.class);
}
#Test
{
final MyClass myClass = new MyClass();
myClass.userService = userService;
myClass.deleteUser();
verify(userService, times(1)).getAdminUser(1);
verify(userService, times(1)).deleteUser(0);
}
}
Note that there is a one-argument only verify() variant, which is exactly equivalent to having times(1) as the second argument. There is also never().
If for instance you wanted to test that the .deleteUser() method was not called with any argument, you'd do:
verify(userService, never()).deleteUser(anyInt());

Categories