Getting org.mockito.exceptions.misusing.UnfinishedStubbingException: - spring-boot

//Test code
class Topic_Service_test
{
#Mock
private Topic_Repository topic_repository;
#InjectMocks
private Topic_Service topic_service = Mockito.spy(new Topic_Service());
#Test
void get_topic_test()
{
Topic_Table topic = new Topic_Table(2,"java");
Mockito.when(topic_repository.findById(Mockito.anyInt()))
.thenReturn(Optional.of(topic));
Mockito.doReturn(topic).when(topic_service.get_topic(2));//.thenReturn(topic);
Assertions.assertEquals(topic,topic_service.get_topic(2));
}
}
class Topic_Service
{
#Autowired
private Topic_Repository topic_repository;
public Topic_Table get_topic(int id)
{
System.out.println("get topic exec");
return topic_repository.findById(id).orElse(new Topic_Table());
}
}
According to me, topic_service.get_topic(2); in Topic_Service_test class should return the object according to Mockito.doReturn(topic).when(topic_service.get_topic(2)); but actually
it is showing some error, which I am not getting it.
ERROR SHOWING:-
org.mockito.exceptions.misusing.UnfinishedStubbingException:
Unfinished stubbing detected here:
-> at
io.practice.practice_course_api.
Topic_Service_test.get_topic_test(Topic_Service_test.java:53)
E.g. thenReturn() may be missing.
Examples of correct stubbing:
when(mock.isOk()).thenReturn(true);
when(mock.isOk()).thenThrow(exception);
doThrow(exception).when(mock).someVoidMethod();
Hints:
1. missing thenReturn()
2. you are trying to stub a final method, which is not supported
3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if
completed

You're using the wrong syntax. It should be:
Mockito.doReturn(topic).when(topic_service).get_topic(2);
That is the syntax you want to use on spies to avoid side-effects (for example: if the method invocation would throw an exception).
#Mock
private Topic_Repository topic_repository;
#InjectMocks
private Topic_Service topic_service = Mockito.spy(new Topic_Service());
Also instead of using it like this, the cleaner way would be to use constructor injection. Consider adding a constructor that has a parameter Topic_Repository and then manually create the spy in your test.

Related

Spring boot with Mockito mocking NamedParameterJdbcTemplate

Trying to unit test a method which is defined as :
public void myMethod(List<? extends MyModel> model){
int[] result = namedParameterJdbcTemplate.batchUpdate("update query", SqlParameterSourceUtils.createBatch(model));
}
In my test class i am defining test method as
class MyTestClass{
#Mock
NamedParameterJdbcTemplate namedParameterJdbcTemplate;
#InjectMocks
MyDao dao;
#Test
public void testMyMethod() {
final int[] rowsAffected = new int[]{1,2};
when(namedParameterJdbcTemplate.batchUpdate(any(), SqlParameterSourceUtils.createBatch(Arrays.asList(anySet())))).thenReturn(rowsAffected);
List<MyModel> myModels = new ArrayList<>();
MyModel mymodel = new MyModel();
mymodel.setSomeParam("");
myModels.add(mymodel);
dao.myMethod(myModels);
}
}
While running this test method , i am getting NullPointerException in called method(myMethod()). int[] result is coming as null. My understanding is it should get the result from the stub in the mock.
Please help me understand what am i doing wrong.
It seems that you're not using the correct import for any() because if it would be the correct ArgumentMatchers.any() from Mockito, Mockito would complain that you don't use an ArgumentMatcher for both parameters of .batchUpdate().
You can statically import it with import static org.mockito.ArgumentMatchers.*; or use ArgumentMatchers.any().
So as first step, try the following:
when(namedParameterJdbcTemplate.batchUpdate(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(rowsAffected);
or be less generic and match the return type of SqlParameterSourceUtils.createBatch() with:
// I don't know what SqlParameterSourceUtils.createBatch() returns, so you might have to adjust it
when(namedParameterJdbcTemplate.batchUpdate(ArgumentMatchers.any(), ArgumentMatchers.eq("SOME RETURN"))).thenReturn(rowsAffected);
It worked by adding the cast to the Argument matchers:
Updated Code :
when(namedParameterJdbcTemplate.batchUpdate(anyString(), (SqlParameterSource[]) any())).thenReturn(rowsAffected);

Mockito throwing NPE in Spring test class #BeforeAll method

I'm trying to mock a service using Mockito and setting up all the method invocations in a #BeforeAll method. The code is the following:
#SpringBootTest
#AutoConfigureMockMvc(addFilters = false)
public class VirtualMachineServiceIntegrationTests {
#MockBean
static VirtualMachineService virtualMachineService;
#Autowired
private MockMvc mockMvc;
#Autowired
private ObjectMapper objectMapper;
static String courseId;
static String studentId;
static Long teamId;
static Long vmId;
static SystemImage os;
static VirtualMachineDTO virtualMachineDTO;
static ConfigurationDTO configurationDTO;
#BeforeAll
static void beforeAll() {
studentId = "student";
courseId = "course";
teamId = 1L;
vmId = 1L;
os = SystemImage.WINDOWS_10;
virtualMachineDTO = VirtualMachineDTO.builder()
.id(1L)
.num_vcpu(2)
.disk_space(1000)
.ram(4)
.status(VirtualMachineStatus.OFF)
.build();
configurationDTO = ConfigurationDTO.builder()
.id(1L)
.min_vcpu(2)
.min_disk(1000)
.min_ram(4)
.max_vcpu(12)
.max_disk(2000)
.max_ram(16)
.max_on(4)
.tot(20)
.build();
Mockito.when(Mockito.any(VirtualMachineService.class).createVirtualMachine(Mockito.anyString(), Mockito.anyLong(), Mockito.anyString(), Mockito.anyInt(), Mockito.anyInt(), Mockito.anyInt())).thenReturn(virtualMachineDTO);
}
}
The NPE is throwed by Mockito even without the thenReturn method. If I move this line
Mockito.when(Mockito.any(VirtualMachineService.class).createVirtualMachine(Mockito.anyString(), Mockito.anyLong(), Mockito.anyString(), Mockito.anyInt(), Mockito.anyInt(), Mockito.anyInt())).thenReturn(virtualMachineDTO);
inside a #Test method then, after throwing a NPE, it will output this:
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Misplaced or misused argument matcher detected here:
-> at it.polito.ai.backend.VirtualMachineServiceIntegrationTests.createVirtualMachine(VirtualMachineServiceIntegrationTests.java:87)
-> at it.polito.ai.backend.VirtualMachineServiceIntegrationTests.createVirtualMachine(VirtualMachineServiceIntegrationTests.java:87)
-> at it.polito.ai.backend.VirtualMachineServiceIntegrationTests.createVirtualMachine(VirtualMachineServiceIntegrationTests.java:87)
-> at it.polito.ai.backend.VirtualMachineServiceIntegrationTests.createVirtualMachine(VirtualMachineServiceIntegrationTests.java:87)
-> at it.polito.ai.backend.VirtualMachineServiceIntegrationTests.createVirtualMachine(VirtualMachineServiceIntegrationTests.java:87)
-> at it.polito.ai.backend.VirtualMachineServiceIntegrationTests.createVirtualMachine(VirtualMachineServiceIntegrationTests.java:87)
-> at it.polito.ai.backend.VirtualMachineServiceIntegrationTests.createVirtualMachine(VirtualMachineServiceIntegrationTests.java:87)
You cannot use argument matchers outside of verification or stubbing.
Examples of correct usage of argument matchers:
when(mock.get(anyInt())).thenReturn(null);
doThrow(new RuntimeException()).when(mock).someVoidMethod(anyObject());
verify(mock).someMethod(contains("foo"))
This message may appear after an NullPointerException if the last matcher is returning an object
like any() but the stubbed method signature expect a primitive argument, in this case,
use primitive alternatives.
when(mock.get(any())); // bad use, will raise NPE
when(mock.get(anyInt())); // correct usage use
Also, this error might show up because you use argument matchers with methods that cannot be mocked.
Following methods *cannot* be stubbed/verified: final/private/equals()/hashCode().
Mocking methods declared on non-public parent classes is not supported.
I'm new at Spring testing and Mockito so I cannot figure it out what I'm doing wrong. Any help appreciated, thanks.
There are multiple things a bit strange here. The main/misunderstanding problem is:
Mockito#when is used to tell a concrete mock what to do on specific method call.
So normally it goes something like this:
Mockito.when(mock.doSomeThings(anyString()).thenReturn("whatever");
Applying this pattern to your code, this should do the trick:
Mockito.when(virtualMachineService.createVirtualMachine(Mockito.anyString(), Mockito.anyLong(), Mockito.anyString(), Mockito.any Int(), Mockito.anyInt(), Mockito.anyInt())).thenReturn(virtualMachineDTO);
Besides this, it looks strange to that you declared everything as static.
I would remove static from all class members and change #BeforeAll to #Before or #BeforeEach (depending on if you use JUnit 4 or 5).

Value of doReturn not used

I use spring boot 2.
I search to test a private method in the facade
#RunWith(SpringRunner.class)
#SpringBootTest
public class SamplingsFacadeTest {
#Autowired
private SamplingsFacade facade;
#MockBean
private SamplingsService samplingsService;
#Test
public void exampleTest() throws Exception {
List<Samplings> samplings = new ArrayList<>();
Samplling sampling = new Samplings();
..
samplings.add(sampling);
//fake call
Mockito.doReturn(samplings).when(samplingsService.getSamplingContainingNonCompliantTest());
//real call
List<FactoryEmailNCDto> factoryEmails = Whitebox.invokeMethod(facade, "prepareDataNoncompliantSampling");
}
public List<Samplings> getSamplingContainingNonCompliantTest() {
return samplingsRepository.findSamplingContainingNonCompliantTest();
}
In Facade In
private List<FactoryEmailNCDto> prepareDataNoncompliantSampling() {
List<FactoryEmailNCDto> factoryEmailNC = new ArrayList<>();
List<Samplings> samplings = samplingsService.getSamplingContainingNonCompliantTest();
for (Samplings sampling : samplings) {
...
}
}
Why when I debug, samplings is null and not the value I created
Mockito.doReturn(samplings)
.when(samplingsService.getSamplingContainingNonCompliantTest());
One potential problem is that doReturn takes the form doReturn(value).when(mock).method(), not doReturn(value).when(mock.method()). The latter is considered an incomplete stubbing. Instead, it should look like this:
Mockito.doReturn(samplings)
.when(samplingsService)
.getSamplingContainingNonCompliantTest();
Note that there may be other problems with your test; the code you've written expects samplingsService to be public and non-final, and your getSamplingContainingNonCompliantTest() to likewise be public, non-static, and non-final, but the code sample you have does not confirm that. You may want to call Mockito.validateMockitoUsage() in an #After method, or use a #Rule that handles Mockito annotations and cleanup for you.

Exception while getting values from Mocked object using Mockito

I am writing junit using mockito for a Spring #component class.
When it try to access the static field from final constant file throwing Null pointer exception.
CruserDomainTest
#RunWith(MockitoJUnitRunner.class)
public class CruserTest {
#InjectMocks
CruserDomain eDomain = new CruserDomain();
#Test
public void testGetCruseById() throws Exception,
{
String cCode = "AA";
int employeeId = 21305;
when(
cruseRepository.getTestId(
anyString(), anyInt())).thenReturn(
buildAndReturnList());
when(
payDomain.getRefPay(anyString(),
anyString(), anyString(), anyString()))
.thenReturn(buildPay());
CruseMember expectedResponse = eDomain.getMemberById(
airlineCode, employeeId);
}
CruserDomain
//getting null pointer exception in the below line execution
//while getting the current month
public CruseMember getMemberById(String cCode, int employeeId)
throws Exception {
//Some code //
if (contractMonth.getType().equals(
CruseConstant.CURRENT_MONTH)) {
currentMonthStartDate = cMonth.getStartDate();
} else if (contractMonth.getType().equals(
CruseConstant.OTHER_MONTH)) {
nextMonthStartDate = cMonth.getStartDate();
}
CruseConstant:
public final class CruseConstant {
public static final String CURRENT_MONTH = "C";
public static final String OTHER_MONTH = "O";
}
I tried with ReflectionTestutils but throwing exception while junit starts.
Help me on how to lookup final class static variables in the injectMocked class.
I strongly advise you to not mock domain objects, instead I would craft builders that can generate those objects.
Also in the code snippet #InjectMocks has no mock to inject, so injects nothing, mock fields should be declared in the test class. However I stress the point of not mocking the domain !
We've written this page on how to write good tests, I think TDD practitioners should read it, wether they use mockito or not. Lot of people contributed to refine this wiki page.
=> https://github.com/mockito/mockito/wiki/How-to-write-good-tests
It is really hard to understand your code because you have replaced the interesting parts with comments, but I would guess that you get a NPE because
contractMonth
is null. That is because you did not mock and/or forgot to define the behaviour of the class that you get the contractMonth from (CruserRepository?)

Why doesn't Mockito's when() get triggered?

I need to test a service class, but when I try to mock the dao class, it doesn't get triggered, thus not able to use ThenReturn().
I think that the problem is because I use an interface for my Dao and #Autowired in the service class (Spring MVC 3.1):
The interface:
public interface TestDao {
int createObject(Test test) throws NamingException;
}
The implementation:
#Repository
public class TestDaoImpl implements TestDao {
#Override
public int createObject(Test test) {
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(new InsertNewTest(test), keyHolder);
return ((java.math.BigDecimal)keyHolder.getKey()).intValue();
}
}
The service:
public class RegTest {
#Autowired
TestDao testDao;
public int regTest(int .....) {
.
.
int cabotageId = testDao.createObject(test);
}
}
In the test I have:
#RunWith(MockitoJUnitRunner.class)
public class TestRegService {
#InjectMocks
private RegTest regTest = new RegTest();
#Mock
TestDao testDao;
#Test()
public void test() {
.
when(testDao.createObject(null)).thenReturn(100);
.
}
testDao.createObject(null) returns 0 (due to being mock'ed) and not 100 as I is trying to achieve.
Can anybody help, please?
Problem solved!
It was the passing test-object to createObject() that did not match. Using
testDao.createObject(any(Test.class))
did the trick!
If your test is actually passing a value to createObject, then when(testDao.createObject(null)... never gets matched. Rather than matching on null, you could match any instance of Test with testDao.createObject(any(Test.class))...
Also when you tried later to supply new Test() as the argument to match, it will literally try to match on that exact instance of Test, but presumably your real code is new-ing up a different one. So the use of Matchers.any(Test.class) as the parameter to match is the way to go.
Mockito injection mechanism don't know about Spring #Autowired or CDI #Inject annotations. It just tries to find the best candidate given the type and the name of the mock, and it can lookup private fields too. See the javadoc of #InjectMocks : http://docs.mockito.googlecode.com/hg/1.9.0/org/mockito/InjectMocks.html
The semantic you are using is correct, though if you are experiencing issues, I would rather look for incorrect interactions or incorrect arguments.
Are you sure the test variable in regTest.regTest(int...) is really null when passed to testDao.createObject(test) ?
I don't know if this is a typo in the example, but you have RegTest.regTest() calling createTest() rather than createObject(). Otherwise, I don't think #Autowired has anything to do with it, since your test itself is not running in a container with Spring management. If it is not a typo, and createTest is in fact a real and different method from createObject, then the default behaviour of a mocked object in Mockito is to return the appropriately-typed zero for numeric return types.
I think that you're right about the autowire not getting called. You could inject the dao yourself using the setTestDao() call instead. Mockito also supports spy which allows you to trace the objects code and just replace functions instead.

Resources