Junit - mockito Wanted but not invoked: - java

Am writting test class for my service implementation class. That service impl class having communication with my repository interface for DB action.
Code is working properly, but while i was writting the test cases for this implementation and getting "wanter but not invoked" error from junit.
Please find my classes below.
Following is my Repository interface
public interface UserRepository extends JpaSpecificationExecutor<UserDeactivationThreshold>,CrudRepository<UserDeactivationThreshold,Long> {
#Query("SELECT bt from BusinessTypes bt where bt.code = :businessTypeCode")
BusinessTypes findByBusinessCodeId(#Param("businessTypeCode") String businessTypeCode);
}
Following is my Service interface
public interface UserDeactivationThresholdService {
public List<UserDeactivationThreshold> getThresholdValue(String businessTypeName);
}
Following is my Service Implementation class
#Service
#Transactional(readOnly = true)
public class UserDeactivationThresholdServiceImpl implements UserDeactivationThresholdService {
private UserRepository userRepository;
#Autowired
public UserDeactivationThresholdServiceImpl(UserRepository userRepository,SecurityClient securityClient, EmailDispatcherService emailDispatcherService) {
this.userRepository = userRepository;
}
#Override
public List<UserDeactivationThreshold> getThresholdValue(String businessTypeName){
return userRepository.findByBusinessType(businessTypeName);
}
}
Please find my Test class
#RunWith(MockitoJUnitRunner.class)
public class UserDeactivationThresholdServiceImplTest {
#Mock
private UserRepository userRepository;
#Mock private UserDeactivationThresholdServiceImpl userDeactivationThresholdServiceImpl;
#Test
public void shouldGetThresholdValueTest() {
UserDeactivationThreshold userDeactivationThreshold = make(a(UserDeactivationThresholdMaker.BCP));
when(userRepository.findByBusinessType("BCP")).thenReturn(asList(userDeactivationThreshold));
verify(userRepository, times(1)).findByBusinessType("BCP");
}
}
Following errors that am getting :
Wanted but not invoked:
userDeactivationThresholdRepository.findByBusinessType(
"BCP"
);
-> at com.core.service.impl.UserDeactivationThresholdServiceImplTest.shouldGetThresholdValueTest(UserDeactivationThresholdServiceImplTest.java:58)
Actually, there were zero interactions with this mock.
* Update *
I tried in this way also, but that also not worked.
verify(userDeactivationThresholdServiceImpl, times(1)).getThresholdValue("BCP");
Following error that i was getting.
-> at com.core.service.impl.UserDeactivationThresholdServiceImplTest.shouldGetThresholdValueTest(UserDeactivationThresholdServiceImplTest.java:58)
Actually, there were zero interactions with this mock.
* Update 2 *
I have added the below code in to my test class. But now am getting the different issue "The method is(Integer) is ambiguous for the type UserDeactivationThresholdServiceImplTest"
List<UserDeactivationThreshold> userDeactivationThresholdList = userDeactivationThresholdServiceImpl.getThresholdValue("BCP");
assertThat(userDeactivationThresholdList.size(), is(1));
Am getting the below messiage for is(1).
The method is(Integer) is ambiguous for the type UserDeactivationThresholdServiceImplTest

As others pointed out already you made the usual beginner mistakes:
Do not mock the class under test.
Make sure that your mocks are injected into your class under test, either by using annotations (#Mock, #InjectMocks) or by providing the references to the mock manually to the class under test.
Use the instance of your class under test in the test to actually test something.
Make sure to read the documentation and a tutorial (e.g. this, this or this) again.
There are also plenty of similiar question to be found here with answers that provide some code examples as well.

Related

Mockito mock returning Null value from repository

I'm trying to test my service implementation with JUNIT5. I don't quite understand whats going wrong but my UserRepository doesn't seem to be returning a value.
I have tested to see if the UserRepository has been used with:
verify(repository, times(1)); And the response was "Wanted but not invoked...Actually, there were zero interactions with this mock"
Here is the Test Class:
#ExtendWith(MockitoExtension.class)
public class UserServiceTest {
#Mock
UserRepository repository;
#InjectMocks
UserServiceImpl userServiceImpl;
UserModel inputUserModel;
#BeforeEach
public void setUp() throws Exception {
inputUserModel = new UserModel();
inputUserModel.setEmail("testemail#gmail.com");
inputUserModel.setFirstName("john");
inputUserModel.setLastName("doe");
inputUserModel.setPassword("test");
inputUserModel.setMatchPassword("test");
User inputUser = User.builder()
.email(inputUserModel.getEmail())
.firstName(inputUserModel.getFirstName())
.lastName(inputUserModel.getLastName())
.password(inputUserModel.getPassword())
.timeCreated(Timestamp.valueOf(LocalDateTime.now(ZoneId.systemDefault()))).userID(1)
.build();
User outputUser = User.builder().
email(inputUserModel.getFirstName()).
password(inputUserModel.getLastName()).
lastName(inputUserModel.getFirstName())
.firstName(inputUserModel.getFirstName())
.timeCreated(Timestamp.valueOf(LocalDateTime.now(ZoneId.systemDefault()))).userID(1).build();
Mockito.when(repository.save(inputUser)).thenReturn(outputUser);
}
#Test
public void whenSaveUser_ThenUserHasID(){
Assertions.assertEquals(1, userServiceImpl.saveUser(inputUserModel).getUserID());
}
}
The error that I am getting:
org.mockito.exceptions.misusing.PotentialStubbingProblem:
Strict stubbing argument mismatch. Please check:
- this invocation of 'save' method:
repository.save(
User(userID=0, email=testemail#gmail.com, timeCreated=2022-12-14 03:18:24.0435578, password=test, firstName=john, lastName=doe)
);
-> at com.jschwery.securitydemo.service.Implementations.UserServiceImpl.saveUser(UserServiceImpl.java:37)
- has following stubbing(s) with different arguments:
1. repository.save(
User(userID=1, email=testemail#gmail.com, timeCreated=2022-12-14 03:18:24.0235563, password=test, firstName=john, lastName=doe)
);
My Service Class that I'm creating the test for:
public class UserServiceImpl implements UserService {
UserRepository userRepository;
#Autowired
public UserServiceImpl(UserRepository repository){
this.userRepository = repository;
}
#Override
public User saveUser(UserModel userModel) {
if(!Objects.equals(userModel.getPassword(), userModel.getMatchPassword())){
throw new UserException("Passwords do not match");
}
User user = User.builder().
email(userModel.getEmail()).
firstName(userModel.getFirstName()).
lastName(userModel.getLastName()).
password(userModel.getPassword()).
timeCreated(Timestamp.valueOf(LocalDateTime.now(ZoneId.systemDefault()))).build();
User returnedUser = userRepository.save(user);
System.out.println(returnedUser.getEmail());
System.out.println("userID" + returnedUser.getUserID());
return returnedUser;
}
}
Thanks for reading! :)
I guess that your User class has an equals/hashCode defined either on the userID field or on all fields. When you mock your repository in your setUp method, you define what the method should do when it is called with the exact object that you specified, comparing the given object to the object specified in the mock by calling the equals/hashCode method.
You define the User object in your setUp method to have the userID 1 but in your UserServiceImpl the userID is not ever set (as it is generated by the persistence layer). Therefore the equals/hashCode check to determine if Mockito should execute the stub logic will never be called because the object passed by the UserServiceImpl will never be equals to the one that you defined in your mock.
There are several ways how you can solve this.
1) Integration test
My advice would be to convert your Unit-Test to a #SpringBootTest. There is no value in testing mocked behaviour. If this test was an integration test, you would test that the repository inserts the User into the database and generates an ID with your assertion.
2) Unit test
If you want to mock the repository, you should use an any() matcher for the input argument and then do what the repository would do, namely set the id:
when(repository.save(any(User.class))).thenAnswer(invocation -> {
final User entity = invocation.getArgument(0);
ReflectionTestUtils.setField(entity, "userID", RandomUtils.nextLong());
return entity;
});
I would then assert, that the userID is not null, as the userID will be randomly generated as it would in production:
#ExtendWith(MockitoExtension.class)
public class UserServiceTest {
#Mock
private UserRepository repository;
#InjectMocks
private UserServiceImpl userServiceImpl;
#Test
void saveUser_userHasID(){
// Arrange
final UserModel inputUserModel = new UserModel();
inputUserModel.setEmail("testemail#gmail.com");
inputUserModel.setFirstName("john");
inputUserModel.setLastName("doe");
inputUserModel.setPassword("test");
inputUserModel.setMatchPassword("test");
when(repository.save(any(User.class))).thenAnswer(invocation -> {
final User entity = invocation.getArgument(0);
ReflectionTestUtils.setField(entity, "userID", RandomUtils.nextLong());
return entity;
});
// Act
final User user = userServiceImpl.saveUser(inputUserModel);
// Assert
assertThat(user.getUserID()).isNotNull();
}
}
I highly recommend to use AssertJ for your assertions as it offers fluent asssertions and way more assertion methods than JUnit.
tl;dr
Spring data can't generate a userID through a simple unit test with a mock, you will need a spring context running in an Integration test.
Details
There are two fields leading to the error you are having : UserID and timeCreated.
For the timeCreated field : in your test you create a inputUser
object that you use for your mock. the problem is that this object
inputUser is NOT the one used by your method under test
saveUser(UserModel userModel) you could clearly see the that the
timestamp differs in the erreor between the two objects.
For the UserID field : again you give your expect your mock to use
the inputUser object. this object has userID = 1. but in the real
method saveUser(UserModel userModel) this field is not set
explicitly so the default value will be set to 0 you could see that
also in the error.
Now since your test case whenSaveUser_ThenUserHasID is meant to verify that a saved record has an ID, you can't do it with a mock. The ID is generated by the Spring Data you are using and yo make it run, you should use and Integration test to run your spring context in your test in order for your spring data to be able to generate an ID for your user, here is a previous question that will be helpful for you to do so. With this, you will neither need the inputUser in your test nor the mock. (You can use #DataJpaTest from JUnit 5 or #SpringBootTest...)

How to test a service or do it right mock? Java11, Spock Framework

Colleagues, I welcome you all! Tell me how to decide, or how to act. (Java11, SpringBoot, testing - Spock Framework) I need to write a test that will test a class method, the whole problem is that the method of the class under test calls another service through inheritance, which is not declared in the class under test, but in its abstract ancestor. How to test such a story? If this service were declared in the class under test itself, then everything is clear, I would create a mock in the test and pass it to the constructor, but what if this service is located at the ancestor? I am attaching an example code below.
// The class to be tested
#Service
public class ServiceForTest extends AbstractComponent{
public String methodForTest (String s) {
return someService.generateString(s);
}
}
//An abstract class from which the tested one is inherited and which contains the service
public class AbstractComponent {
#Autowired
protected SomeService someService;
}
public interface SomeService {
String generateString(String s);
}
#Service
public class SomeServiceImpl implements SomeService{
#Override
public String generateString(String s) {
return s;
}
}
And below is an example of what I would do if the service was in the class being tested
//TestClass
#Service
public class ServiceForTest extends AbstractComponent{
final SomeService someService;
public ServiceForTest(SomeService someService) {
this.someService = someService;
}
public String methodForTest (String s) {
return someService.generateString(s);
}
}
class test groovy, Spock Framework
class ServiceForTestTest extends Specification {
ServiceForTest serviceForTest
void setup(){
SomeService someServiceMock = Mock(SomeService)
someServiceMock.generateString("TEST") >> "TEST"
serviceForTest = new ServiceForTest(someServiceMock)
}
def "Test for return current value"(){
when:
def methodForTest = serviceForTest.methodForTest("TEST")
then:
methodForTest == "TEST"
}
}
You use #Autowired, i.e. some kind of dependency injection framework such as Spring or Java EE CDI. Those frameworks have testing support. Specifically for Spring testing, Spock has a Spring module which you can use. I am not a Spring user, so I cannot tell you how to exactly do that, but the documentation is pretty good.
As a general answer, even without any framework support you can test this easily, if you follow the convention to put the test into the same package as the class under test. Because the field you want to inject a mock into is protected, it means for the JVM that all subclasses, but also other classes in the same package have access to it. I.e., you can simply set the value:
serviceForTest = new ServiceForTest()
serviceForTest.someService = someServiceMock
Or, more elegantly using a Groovy-style constructor which implicitly sets field values:
serviceForTest = new ServiceForTest(someService: someServiceMock)
Generally, I recommend constructor or setter injection rather than relying on field injection (especially when fields are private), because then with regard to testability you have a strict dependency to your DI framework and cannot easily write unit tests. So if you can refactor, I recommend you to do it. You just noticed that testing such things can be kind of a headache, unless you have a way out like in this particular case with the protected field. But that is not so super refactoring-friendly.

How to write mockito test cases for factory class

I was new for writing test cases. I want to write the Mockito test cases for the below :
#Component
public class FactoryClass {
#Autowired
private DataService dataService;
#Autowired
private ModelMapper modelMapper;
public List<TestEntity> convertEventToEntity(CEvent cEvent, Event event){
List<TestEntity> TestEntityList =new ArrayList<>();
if (!CollectionUtils.isEmpty(cEvent.getOrderDetails())) {
for (CEventDetail cEventDetail : cEvent.getCEventDetail()) {
log.info("Creating TestEntity entity ..");
TestEntity testEntity = new TestEntity();
testEntity.setEId(event.getEId());
testEntity.setActId(event.getHeaderReference().getActId());
testEntity.setEName(event.getEType());
tfbUpgrades.setPO(cEventDetail.getPO());
TestEntityList.add(testEntity);
}
}
return TestEntityList;
}
}
Can anyone please help me with the code sample to write mockito test cases for the factory class.
The only thing you might want to test in this class is the public convertEventToEntity method. The class has two dependencies - dataService and modelMapper. But they are not used in the code, so you don't need to mock them. So you can write tests for this class without using Mockito. Just create an object of FactoryClass and call the method with some input CEvent and Event objects. You can assert on expected List<TestEntity>.
You can test several logical paths in this method. For example, there's an if condition that does something only if cEvent's order details are present. So you can have two test cases where you pass cEvent with and without order details and you can verify that the code is executed correctly in both cases.

Test class with nested dependencies

I'm testing a class with nested (Autowired) dependencies. The class implements businesslogic for making alterations in the backend. Specifically the test should assert that when a certain backend call returns an error:
No more backend calls are made
The response object returns an error
I dont know how the do the latter.
My class looks something like this:
public class Handler {
#Autowired
private DaoImpl dao;
#Autowired
private SpecificUtil util1;
#Autowired
private GeneralUtil util2;
#Autowired
private Helper helper;
public Response doSomethingClever(Request request) {
// calls to dao
// logic with help of util and helper classes
}
}
The testclass:
public class HandlerTest {
#Spy
private DaoImpl dao;
#Mock
private SpecificUtil util1;
#Mock
private GeneralUtil util2;
#Mock
private Helper helper;
#InjectMocks
Handler handler;
#Test
public void testDoSomethingClever() {
// set up dao to fail
QueryResult error = getErrorResult();
org.mockito.Mockito.when(dao.queryBackEnd(any(SpecificQuery.class))).thenReturn(error);
// perform query
Request request = getTestRequest();
Response errorResponse = handler.doSomethingClever(request);
// verify that either:
// Response has errors - fails
// because helper classes are mocks, have not set the error
assertNotNull(response.getErrorMessage());
// the method setErrors of Response was called once - fails
//because the setError was called earlier!
Response spyResponse = Mockito.spy(errorResponse);
verify(spyResponse, times(1)).setError(anyString);
//verify no other calls are made except the queryBackEnd call - this part works
org.mockito.Mockito.verify(dao).queryBackEnd(any(SpecificQuery.class));
org.mockito.Mockito.verifyNoMoreInteractions(dao);
}
}
The Response object is created in the Handler class. If i check the returned response, no interactions will be recorded by Mockito, because the interactions have taken place prior to calling Mockito.spy.
I have tried making it an integration test, by using #Spy instead of #Mock. The idea is to instantiate all the nested dependencies except for the dao and get a proper Response to test for errors. But this does not work because some of the #Autowired helper and utility classes also have #Autowired dependencies and these nested dependencies are not instantiated during testing.
Is there any way to inject #Spy objects into other #Spy objects with Mockito?
Or is there some other solution in this case? Sould i write my own mockobjects?
A unit test should test the code of a specific unit only (here the Handler class). This includes interacting with the dependencies.
From what you wrote in your question and comments your handle method looks something along these lines:
public class Handler {
#Autowired
private DaoImpl dao;
#Autowired
private Util util;
public Response doSomethingClever(Request request) {
SpecificQuery specificQuery = new SpecificQuery();
specificQuery.setSomeData(request.getSomeData());
IntermidiateResponse intermidiateResponse = dao.queryBackEnd(specificQuery);
Response response = util.processIntermidiateResult(intermidiateResult);
return response;
}
}
There are a few interactions to unit test here:
Given a Request instance assert that DaoImpl::queryBackEnd method is called with a SpecificQuery instance that has someData property set to someData property from the Request object
Given a mocked IntermidiateResponse being returned from the DaoImpl::queryBackEnd method assert that this result is passed on to the Util::processIntermidiateResult method
Given a mocked Response being returned from the Util::processIntermidiateResult method assert that this is exactly what gets returned from the handle method
This way you have 100% coverage on the Handler::handle method. If you have some more calls in the response processing pipeline you test them all accordingly.
Hope this answers your question. Good luck
There are two options, one is to test the Handler in isolation, mocking everything else. See the answer by jannis. The other option is to control/mock the in- and output of the Handler, and treat the Handler and all its utility classes as a black box.
I have opted for this last option because it means that i can refactor the utility-classes, and the Handler class itself, and that tests will succeed as long as i don't change what the Handler does. It does mean that i have departed somewhat from doing unit testing and that i'm really doing more of an integration test.
For this i mock the Dao class, so that i can have it return an error at the desired point and so that i can assert that no further calls are made after the error.
It is the only class i mock, so i need to inject it into the Handler. This is possible with Springs ReflectionTestUtils (I did'nt know about this yesterday)
The testcode then becomes shorter:
public class HandlerTest {
#Autowired
private Handler handler;
#Test
public void testDoSomethingClever() {
// set up dao to fail
Dao mockDao = org.mockito.Mockito.mock(DaoImpl.class);
QueryResult error = getErrorResult();
org.mockito.Mockito.when(dao.queryBackEnd(any (SpecificQuery.class))).thenReturn(error);
// inject the dao
ReflectionTestUtils.setField(handler, "dao", mockDao);
// perform query
Request request = getTestRequest();
Response errorResponse = handler.doSomethingClever(request);
// verify that Response has errors
assertNotNull(response.getErrorMessage());
//verify no other calls are made except the queryBackEnd call
org.mockito.Mockito.verify(dao).queryBackEnd(any(SpecificQuery.class));
org.mockito.Mockito.verifyNoMoreInteractions(dao);
}
}

Mockito, Testing an object that relies on injected dependencies (Spring)?

I'm new to using Mockito and am trying to understand a way to make a unit test of a class that relies on injected dependencies. What I want to do is to create mock objects of the dependencies and make the class that I am testing use those instead of the regular injected dependencies that would be injected by Spring. I have been reading tutorials but am a bit confused on how to do this.
I have one the class I want to test like this:
package org.rd.server.beans;
import org.springframework.beans.factory.annotation.Autowired;
public class TestBean1 {
#Autowired
private SubBean1 subBean1;
private String helloString;
public String testReturn () {
subBean1.setSomething("its working");
String something = subBean1.getSomething();
helloString = "Hello...... " + something;
return helloString;
}
Then I have the class that I want to use as a mock object (rather than the regular SubBean1 class, like below:
package org.rd.server.beans.mock;
public class SubBean1Mock {
private String something;
public String getSomething() {
return something;
}
public void setSomething(String something) {
this.something = something;
}
}
}
I just want to try running a simple test like this:
package test.rd.beans;
import org.rd.server.beans.TestBean1;
import junit.framework.*;
public class TestBean1Test extends TestCase
{
private TestBean1 testBean1;
public TestBean1Test(String name)
{
super(name);
}
public void setUp()
{
testBean1 = new TestBean1();
// Somehow inject the mock dependency SubBean1Mock ???
}
public void test1() {
assertEquals(testBean1.testReturn(),"working");
}
}
I figure there must be some fairly simple way to do this but I can't seem to understand the tutorials as I don't have the context yet to understand everything they are doing / explaining. If anyone could shed some light on this I would appreciate it.
If you're using Mockito you create mocks by calling Mockito's static mock method. You can then just pass in the mock to the class you're trying to test. Your setup method would look something like this:
testBean1 = new TestBean1();
SubBean1 subBeanMock = mock(SubBean1.class);
testBean1.setSubBean(subBeanMock);
You can then add the appropriate behavior to your mock objects for whatever you're trying to test with Mockito's static when method, for example:
when(subBeanMock.getSomething()).thenReturn("its working");
In Mockito you aren't really going to create new "mock" implementations, but rather you are going to mock out the methods on the interface of the injected dependency by telling Mockito what to return when the method is called.
I wrote a test of a Spring MVC Controller using Mockito and treated it just like any other java class. I was able to mock out the various other Spring beans I had and inject those using Spring's ReflectionTestUtils to pass in the Mockito based values. I wrote about it in my blog back in February. It has the full source for the test class and most of the source from the controller, so it's probably too long to put the contents here.
http://digitaljoel.nerd-herders.com/2011/02/05/mock-testing-spring-mvc-controller/
I stumbled on this thread while trying to set up some mocks for a slightly more complicated situation and figured I'd share my results for posterity.
My situation was similar in the fact that I needed to mock dependencies, but I also wanted to mock some of the methods on the class I was testing. This was the solution:
#MockBean
DependentService mockDependentService
ControllerToTest controllerToTest
#BeforeEach
public void setup() {
mockDependentService = mock(DependentService.class);
controllerToTest = mock(ControllerToTest.class);
ReflectionTestUtils.setField(controllerToTest, "dependantService", mockDependentService);
}
#Test
void test() {
//set up test and other mocks
//be sure to implement the below code that will call the real method that you are wanting to test
when(controllerToTest.methodToTest()).thenCallRealMethod();
//assertions
}
Note that "dependantService" needs to match whatever you have named the instance of the service on your controller. If that doesn't match the reflection will not find it and inject the mock for you.
This approach allows all the methods on the controller to be mocked by default, then you can specifically call out which method you want to use the real one. Then use the reflection to set any dependencies needed with the respective mock objects.
Hope this helps someone down the road as it stumped me for a while.

Categories

Resources