Mockito mock CassandraOperation Slice method - spring-boot

I am using the Mockito framework to write the mock Junit test cases below is my Service class to test the Junit test code
public class UserService {
#Autowired
private CassandraOperations template
public UserDTO getUserDTO(String date, String pagingState) {
Select select = QueryBuilder.select().all()
.from("tbl_user");
select.where(QueryBuilder.eq(date, date));
select.setFetchSize(30);
if (pagingState != null) {
select.setPagingState(PagingState.fromString(pagingState));
}
Slice<UserDTO> usgerDTO = template.slice(select, UserDTO.class);
if(usgerDTO.hasNext()) {
}
return usgerDTO.get();
}
Test case Class is writted
#RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {
#InjectMocks
private UserService service ;
#Mock
private CassandraOperations template;
#Mock
private UserDTO userDTO;
private String date= "2019-09";
#Test(expected = Exception.class)
public void test() {
Slice<UserDTO> userDTO= Mockito.mock(Slice.class);
Select select = Mockito.mock(Select.class);
Mockito.when(template.slice(select, UserDTO.class)).thenReturn(userDTO);
metricReportDTO = service.getUserDTO(date, null);
}
}
I am getting Null values on this line
Slice<UserDTO> usgerDTO = template.slice(select, UserDTO.class);
Can you please helm me how to test template.slice method
Note: I should not use the PowerMockito

Your code snippet doesn't make sense in that you call service.getMetricsReports(date, null) in your test but your UserService code example only has the method getUserDTO. Assuming that is just a typo then you need to use matchers to get the mock to work in your when.
Mockito.when(template.slice(any(Select.class), eq(UserDTO.class))).thenReturn(userDTO);
This means whenever the first param is a class of type Select and the second is equal to UserDTO.class then return the userDTO if those 2 params don't match those conditions it will return null.
You can also make it match the exact Select assuming it has an overridden equals method. In the case where you send a null pagingState then something like:
Select stubSelect = QueryBuilder.select().all()
.from("tbl_user");
stubSelect.where(QueryBuilder.eq(date, date));
stubSelect.setFetchSize(30);
Mockito.when(template.slice(eq(stubSelect), eq(UserDTO.class))).thenReturn(userDTO);

Related

Dependency injection with mockito example

I am very new with Mockito and I don't get the following example (classes were provided, only test to write) and how to solve it.
What I try to do is use a test double for the supplier so that we can control the returned greeting in the test and assert that the GreetingService does not modify the greeting message in any way. Then assert that the returned greeting string is equal to "Hello Andy.".
public class Greeting {
private final String template;
public Greeting(String template) {
this.template = template;
}
public String forName(String world) {
return String.format(template, world);
}
}
#Component
public class GreetingService {
private final Supplier<Greeting> greetingSupplier;
public GreetingService(Supplier<Greeting> greetingSupplier) {
this.greetingSupplier = greetingSupplier;
}
public String greet(String name) {
return greetingSupplier.get().forName(name);
}
}
#Component
public class RandomGreetingSupplier implements Supplier<Greeting> {
private final List<Greeting> greetings = Arrays.asList(
new Greeting("Hello %s."),
new Greeting("Hi %s!"),
);
private final Random random = new Random();
#Override
public Greeting get() {
return greetings.get(random.nextInt(greetings.size()));
}
}
#SpringBootTest
public class GreetingServiceTest {
#Autowired
GreetingService greetingService;
#MockBean
Supplier<Greeting> greetingSupplier;
#Test
void getGreetingForPerson() {
String name = "Andy";
// that test cannot know which greeting will be returned by the supplier
// WHY IS IT NULLPOINTEREXCEPTION AFTER INITIALIZING #MockBean
//String greeting = greetingService.greet(name);
//assertThat(greeting).contains(name);
// WROTE SUCH TEST HERE -> NullPointerException WHY?
Mockito.when(greetingSupplier.get().forName(name)).thenReturn("Hello %s.");
assertThat(greetingSupplier.equals("Hello Andy."));
// THIS IS WORKING & TEST PASSED BUT I GUESS ITS WRONG?
Mockito.when(greetingSupplier.get()).thenReturn(new Greeting("Hello %s."));
assertThat(greetingSupplier.equals("Hello Andy."));
}
}
Mockito.when(greetingSupplier.get().forName(name)).thenReturn("Hello %s.");
You can't chain calls like that, you need to produce intermediate results, like
Supplier<Greeting> supplier = mock(Supplier.class);
Mockito.when(supplier).forName().thenReturn("Hello %s.");
Mockito.when(greetingSupplier.get()).thenReturn(supplier);
For dependency injection, you need to create the subject under test with the mocked Supplier. You can do that in a #Before method for example.
Your mocking is wrong.
Mockito.when(greetingSupplier.get().forName(name)).thenReturn("Hello %s.");
You mocked Supplier<Greeting> and the default behavior is to return null. So when you call greetingSupplier.get() in your first line it returns null. You directly chain forName which nou basicall is null.forName which leads to an error.
Your second part is actually (kind of) correct.
Mockito.when(greetingSupplier.get()).thenReturn(new Greeting("Hello %s."));
You now properly return a response from greetingSupplier.get(). Instead of chaining the call.
However I would argue that your excercise is wrong. Why? When using a Supplier<?> in Spring it actually is a lazy beanFactory.getBean call. You can lazily inject dependencies this way. You should have a mock for Greeting which returns a hardcoded String which you can check.

NullPointerException on mockito spring's NamedParameterJdbcTemplate

i have a DAO class that I am trying to write test cases
Here is modified reproducible code
the DAO class I am trying to test
#Component
public class SomeDAO {
#Autowired
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
public boolean dataInTable(String id) {
String sql = "SELECT COUNT(*) " +
"FROM table1" +
"WHERE id =:id";
MapSqlParameterSource sqlParms = new MapSqlParameterSource();
sqlParms.addValue("id", id
try {
int count = namedParameterJdbcTemplate.queryForObject(sql, sqlParms, Integer.class);
return (count > 0) ? true : false;
} catch (Exception e) {
log.error("Error checking existence of id : " + id);
throw e;
}
}
}
When i run the test, it throws an NullPointer on
int count = namedParameterJdbcTemplate.queryForObject(sql, sqlParms, Integer.class);
so i believe mockito is not returning a value on when, thenReturn
i searched around stack overflow and it looks like what i have should work, but I am getting NullPointerException.
I have also tried using the same value for sql string and a mapObject as the dao class instead of anyString() and anyMap()
but did not work either
Test case
#RunWith(MockitoJUnitRunner.class)
public class SomeDAOTest {
#InjectMocks
SomeDAO someDao
#Mock
NamedParameterJdbcTemplate namedParameterJdbcTemplate;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
}
#Test
public void TestdataInTable(){
//
when(namedParameterJdbcTemplate.queryForObject(anyString(), anyMap(),eq(Integer.class))).thenReturn(1);
assertEquals( true,someDao.dataInTable("123456"));
}
}
Try this,
#Test
public void TestdataInTable() {
Mockito.when(namedParameterJdbcTemplate.queryForObject(Mockito.anyString(),
Mockito.any(SqlParameterSource.class), Mockito.eq(Integer.class))).thenReturn(1);
assertEquals(true, someDao.dataInTable("123456"));
}
The second parameter in queryForObject() is of type SqlParameterSource, which is not directly a map. So it should be, Mockito.any(SqlParameterSource.class).
The current version of your code displays warning in console, which is the best way to debug the issue.
[MockitoHint] TestDao.TestdataInTable (see javadoc for MockitoHint):
[MockitoHint] 1. Unused... -> at TestDao.TestdataInTable(TestDao.java:33)
[MockitoHint] ...args ok? -> at SomeDao.dataInTable(SomeDao.java:26)
Adding this as it may help someone:
I had a similar issue but the reason was very different.
I was getting null pointer exception not just on NamedParameterJdbcTemplate which was annotated with #Mock but also on #InjectMocks.
It so turn out that I was using Junit 5. The above solution will work with Junit 4. To make Mockito use Junit 5, an additional annotation is required. Also make sure you remove #RunWith(MockitoJUnitRunner.class) as this will cause failure. Instead use #ExtendWith(MockitoExtension.class.
Here is an example:
#ExtendWith(MockitoExtension.class)
public class SomeDAOTest {
#InjectMocks
SomeDAO someDao
#Mock
NamedParameterJdbcTemplate namedParameterJdbcTemplate;

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.

Verify a method is called inside a method without calling other methods inside that method

public class ServiceClass {
#Autowired
ConnClient connClient;
public void abc() {
result = connClient.query(arg1, arg2); // verify called once.
allDocsReturned = result.getResults(); // throws NPE
}
}
I need to verify that connClient.query(arg1,arg2) is called at least once. So in the test cases file i am calling the method abc()
#InjectMocks
ServiceClass serviceClass;
#Mock
ConnClient connClient;
#Test
public void testABC() {
serviceClass.abc();
verify(connClient, times(1)).query(arg1,arg2);
}
I get NullPointerException because of the line result.getResults() called above as result is null, and the test case getting failed.
Please help.
You need to mock the call to connClient.query and ResultSet:
#InjectMocks
ServiceClass serviceClass;
#Mock
ConnClient connClient;
#Test
public void testABC() {
ResultSet rs = mock(ResultSet.class);
when(rs.getResults()).thenReturn(//here return the object of type of your variable allDocsReturned);
when(connClient.query(arg1,arg2)).thenReturn(rs);
serviceClass.abc();
verify(connClient, times(1)).query(arg1,arg2);
}
Your class ConnClient is a mock which is why the call connClient.query(arg1, arg2) will return null ad thus a NPE is thrown when dereferencing the result.
In this case you can specify the return value of the method call, i.e.
doReturn(someObject).when(connClient).query(arg1,arg2);
where someObject is allowed to be a mock (alternatively, you can return a concrete value).
Once this is done, result won't be null anymore and no NPE will be thrown.
Note that if result is dereferenced later, you also have to mock the getResults() call.
Edit:
#InjectMocks
ServiceClass serviceClass;
#Mock
ConnClient connClient;
#Mock
Result result;
#Test
public void testABC() {
doReturn(result).when(connClient).query(arg1,arg2);
serviceClass.abc();
verify(connClient, times(1)).query(arg1,arg2);
}
Now result will not be null, however, allDocsReturned will still be null, but will not lead to a NPE with the code posted by you

Is a mock MongoRepository saving objects?

I am using SpringBoot 1.5.9 and try to do Integration testing. Weirdly a MongoRepository.save() method updates the object when called on mock MongoRepository.
I have a Counter Class
public class Counter {
public String id;
public int seq;
public void increaseSeq() {
this.seq += 1;
}
}
And his repository
public interface CounterRepository extends MongoRepository<Counter, String>{
Counter findById(String id);
List<Counter> findAll();
}
And his service
#Service
public class CounterService {
#Autowired private CounterRepository counterRepository;
public Counter findCounter(String id) {
return counterRepository.findById(id);
}
public int getSeqAndIncrease(String id) {
Counter counter = findCounter(id);
if (counter == null) {
return -1;
}
counter.increaseSeq();
counterRepository.save(counter);
return counter.getSeq();
}
}
Now, when I do system integration and try to mock the counterRepository, it happens something that I don't expect. The counterRepository.findById() returns a Counter object where the 'seq' field is increased. Why? Does the counterRepository.save() affect the result in any way (the counterRepository is mocked, hence I suppose that save() should not have any effect)?
#RunWith(SpringRunner.class)
#SpringBootTest
public class FlowServiceTest {
#MockBean private CounterRepository counterRepository;
#Autowired private CounterService counterService;
#Before
public void setUp() {
Mockito.when(counterRepository.save(any(Counter.class))).then(arg -> arg.getArgumentAt(0, Counter.class));
Mockito.when(counterRepository.findById("flow")).thenReturn(new Counter("flow", 10));
}
#Test
public void testSavingInDatabase() {
System.out.println(counterRepository.findById("flow"));
counterService.getSeqAndIncreaseSafe("flow");
System.out.println(counterRepository.findById("flow"));
counterService.getSeqAndIncreaseSafe("flow");
System.out.println(counterRepository.findById("flow"));
}
}
It prints "10 11 12". Why doesn't it print '10 10 10'?
The problem is these lines
counterRepository.save(counter);
return counter.getSeq();
What you should be doing is this
Counter saveCounter = counterRepository.save(counter);
return savedCounter.getSeq();
In getSeqAndIncrease method, you are not returning sequence of the saved object.
By doing this you are making your mock statement for save useless. Because you are not using the value returned from mock.
tl;dr - The returned object from mock is initialized only once in mockito. So I basically got the same reference every time, and since it is a reference not a new object, the values are updated.
Complete answer: When setting
Mockito.when(counterRepository.findById("flow")).thenReturn(new Counter("flow", 10));
, it might seem intuitive to return a new object every time, but the return object is initialised only once when the test starts and will be returned at all subsequent calls.
Then, in my code I do
counter.increaseSeq();
which increases the 'seq' of found object (this object comes from Mockito). Then at the next call, Mockito returns the firstly initialised object which was updated in the meantime; Mockito does not return a new object as it might seem like.

Resources