Mock NamedParameterJdbcTemplate with callback function - unit-testing

Im trying to mock NamedParameterJdbcTemplate inside LaAttributeRepo Calss having below method findFieldByItemId
SqlParameterSource param = new MapSqlParameterSource("laIds", laIds);
List < LaAttributes > laAttributes = jdbcTemplate.query("Select_query", param,
(rs, rowNum) -> new LaAttributes(rs.getString("cloumn1"), rs.getString("cloumn2")));
//jdbcTemplate is NamedParameterJdbcTemplate
I need to mock it in test class below
#Test
public void findFieldsByItemId() {
List < String > itemsId = new ArrayList < > ();
itemsId.add("VZ203");
//NamedParameterJdbcTemplate is mocked.
Mockito.when(mockedNamedParameterJdbcTemplate.query(Mockito.anyString,
Mockito.any(MapSqlParameterSource.class), Mockito.any(ResultSetExtractor.class))).thenAnswer(
(invocationOnMock) -> {
ResultSetExtractor < List < LaAttributes >> resultSetExtractor = invocationOnMock.getArgument(2);
ResultSet rs = Mockito.mock(ResultSet.class);
Mockito.when(rs.getString(ArgumentMatchers.eq("column1")))
.thenReturn("column1");
Mockito.when(rs.getString(ArgumentMatchers.eq("column2")))
.thenReturn("column2");
return resultSetExtractor.extractData(rs);
});
List < LaAttributes > laAttributes = laAttributeRepo.findFieldByItemId(ItemsId);
Assert.assertEquals("column1", laAttributes.get(0).getColumnOne());
}
I am getting list as null for laAttributeRepo.findFieldByItemId(ItemId) Not sure what to do. Can anyone help ?

Related

Unit Testing: Verify that a method was called, without testing frameworks like Mockito or MockK

Not using testing frameworks like MockK or Mockito seems to be becoming more and more popular. I decided to try this approach. So far so good, returning fake data is simple. But how do I verify that a function (that does not return data) has been called?
Imagine having a calss like this:
class TestToaster: Toaster {
override fun showSuccessMessage(message: String) {
throw UnsupportedOperationException()
}
override fun showSuccessMessage(message: Int) {
throw UnsupportedOperationException()
}
override fun showErrorMessage(message: String) {
throw UnsupportedOperationException()
}
override fun showErrorMessage(message: Int) {
throw UnsupportedOperationException()
}
}
With MockK I would do
verify { toaster.showSuccessMessage() }
I do not want to reinvent a wheel so decided to ask. Finding anything on Google seems to be very difficult.
Since this is a thing, I assume the point would be to totally remove mocking libraries and everything can be done without them.
The old school way to do it before any appearance of the mocking library is to manually create an implementation that is just for testing . The test implementation will store how an method is called to some internal state such that the testing codes can verify if a method is called with expected parameters by checking the related state.
For example , a very simple Toaster implementation for testing can be :
public class MockToaster implements Toaster {
public String showSuccesMessageStr ;
public Integer showSuccesMessageInt;
public String showErrorMessageStr;
public Integer showErrorMessageInt;
public void showSuccessMessage(String msg){
this.showSuccesMessageStr = msg;
}
public void showSuccessMessage(Integer msg){
this.showSuccesMessageInt = msg;
}
public void showErrorMessage(String msg){
this.showErrorMessageStr = msg;
}
public void showErrorMessage(Integer msg){
this.showErrorMessageInt = msg;
}
}
Then in your test codes , you configure the object that you want to test to use MockToaster. To verify if it does really call showSuccessMessage("foo") , you can then assert if its showSuccesMessageStr equal to foo at the end of the test.
A lot of people seem to be suggesting the very straight forward solution for this, which totally makes sense. I decided to go a bit fancy and achieve this syntax:
verify(toaster = toaster, times = 1).showErrorMessage(any<String>()).
I created simple Matchers:
inline fun <reified T> anyObject(): T {
return T::class.constructors.first().call()
}
inline fun <reified T> anyPrimitive(): T {
return when (T::class) {
Int::class -> Int.MIN_VALUE as T
Long::class -> Long.MIN_VALUE as T
Byte::class -> Byte.MIN_VALUE as T
Short::class -> Short.MIN_VALUE as T
Float::class -> Float.MIN_VALUE as T
Double::class -> Double.MIN_VALUE as T
Char::class -> Char.MIN_VALUE as T
String:: class -> "io.readian.readian.matchers.strings" as T
Boolean::class -> false as T
else -> {
throw IllegalArgumentException("Not a primitive type ${T::class}")
}
}
}
Added a map to store call count for each method to my TestToaster where the key is the name of the function and value is the count:
private var callCount: MutableMap<String, Int> = mutableMapOf()
Whenever a function gets called I increase current call count value for a method. I get current method name through reflection
val key = object {}.javaClass.enclosingMethod?.name + param::class.simpleName
addCall(key)
In oder to achieve the "fancy" syntax, I created inner subcalss for TestToaster and a verify function:
fun verify(toaster: Toaster , times: Int = 1): Toaster {
return TestToaster.InnerToaster(toaster, times)
}
That function sends current toaster instance to the inner subclass to create new instance and returns it. When I call a method of the subclass in my above syntax, the check happens. If the check passes, nothing happens and test is passed, if conditions not met - and exception is thrown.
To make it more general and extendable I created this interface:
interface TestCallVerifiable {
var callCount: MutableMap<String, Int>
val callParams: MutableMap<String, CallParam>
fun addCall(key: String, vararg param: Any) {
val currentCountValue = callCount.getOrDefault(key, 0)
callCount[key] = currentCountValue + 1
callParams[key] = CallParam(param.toMutableList())
}
abstract class InnerTestVerifiable(
private val outer: TestCallVerifiable,
private val times: Int = 1,
) {
protected val params: CallParam = CallParam(mutableListOf())
protected fun check(functionName: String) {
val actualTimes = getActualCallCount(functionName)
if (actualTimes != times) {
throw IllegalStateException(
"$functionName expected to be called $times, but actual was $actualTimes"
)
}
val callParams = outer.callParams.getOrDefault(functionName, CallParam(mutableListOf()))
val result = mutableListOf<Boolean>()
callParams.values.forEachIndexed { index, item ->
val actualParam = params.values[index]
if (item == params.values[index] || (item != actualParam && isAnyParams(actualParam))) {
result.add(true)
}
}
if (params.values.isNotEmpty() && !result.all { it } || result.isEmpty()) {
throw IllegalStateException(
"$functionName expected to be called with ${callParams.values}, but actual was with ${params.values}"
)
}
}
private fun isAnyParams(vararg param: Any): Boolean {
param.forEach {
if (it.isAnyPrimitive()) return true
}
return false
}
private fun getActualCallCount(functionName: String): Int {
return outer.callCount.getOrDefault(functionName, 0)
}
}
data class CallParam(val values: MutableList<Any> = mutableListOf())
}
Here is the complete class:
open class TestToaster : TestCallVerifiable, Toaster {
override var callCount: MutableMap<String, Int> = mutableMapOf()
override val callParams: MutableMap<String, TestCallVerifiable.CallParam> = mutableMapOf()
override fun showSuccessMessage(message: String) {
val key = object {}.javaClass.enclosingMethod?.name + message::class.simpleName
addCall(key, message)
}
override fun showSuccessMessage(message: Int) {
val key = object {}.javaClass.enclosingMethod?.name + message::class.simpleName
addCall(key, message)
}
override fun showErrorMessage(message: String) {
val key = object {}.javaClass.enclosingMethod?.name + message::class.simpleName
addCall(key, message)
}
override fun showErrorMessage(message: Int) {
val key = object {}.javaClass.enclosingMethod?.name + message::class.simpleName
addCall(key, message)
}
private class InnerToaster(
verifiable: TestCallVerifiable,
times: Int,
) : TestCallVerifiable.InnerTestVerifiable(
outer = verifiable,
times = times,
), Toaster {
override fun showSuccessMessage(message: String) {
params.values.add(message)
val functionName = object {}.javaClass.enclosingMethod?.name + message::class.simpleName
check(functionName)
}
override fun showSuccessMessage(message: Int) {
params.values.add(message)
val functionName = object {}.javaClass.enclosingMethod?.name + message::class.simpleName
check(functionName)
}
override fun showErrorMessage(message: String) {
params.values.add(message)
val functionName = object {}.javaClass.enclosingMethod?.name + message::class.simpleName
check(functionName)
}
override fun showErrorMessage(message: Int) {
params.values.add(message)
val functionName = object {}.javaClass.enclosingMethod?.name + message::class.simpleName
check(functionName)
}
}
companion object {
fun verify(toaster: Toaster, times: Int = 1): Toaster {
return InnerToaster(toaster as TestCallVerifiable, times)
}
}
}
I have not tested this extensively and it will evolve with time, but so far it works well for me.
I also wrote an article about this on Medium: https://sermilion.medium.com/unit-testing-verify-that-a-method-was-called-without-testing-frameworks-like-mockito-or-mockk-433ef8e1aff4

How to use Moq to Verify that PropertyChanged is invoked with the expected object and property name?

Using NUnit and Moq, I'd like to replace the PropertyChanged handler code in the following test by Moq if it makes the test shorter and clearer. I'm currently unclear as to how to do this in Moq, verifying that PropertyChanged is invoked once for IsDirty and once for LocalDatabaseFilePath, each time with the expected object (o in the code). Can anybody advise how to do this with Moq please?
[Test]
[Category("Fast Tests")]
[Category("PropertyChanged Events")]
public void FactoryResetCommand_AllPropertiesChangedInViewModel_PropertyChangedEventsFiredAsExpected()
{
// Arrange
string expectedLocalDatabaseFilePath = "eldfp";
string otherLocalDatabaseFilePath = "other" + expectedLocalDatabaseFilePath;
Mock<IDataStoreSettingsDataModel> stubDataModel = new Mock<IDataStoreSettingsDataModel>();
stubDataModel.Setup(x => x.LocalDatabaseFilePath).Returns(expectedLocalDatabaseFilePath);
IDataStoreSettingsViewModel sutViewModel = new DataStoreSettingsViewModel(
stubDataModel.Object,
ReportExceptionAsync);
sutViewModel.LocalDatabaseFilePath = otherLocalDatabaseFilePath;
sutViewModel.IsDirty = false;
// I'd like to replace the following by Moq if shorter/clearer
int propertyChangedCountIsDirty = 0;
int propertyChangedCountLocalDatabaseFilePath = 0;
object? objIsDirty = null;
object? objLocalDatabaseFilePath = null;
sutViewModel.PropertyChanged += ((o, e) =>
{
switch (e?.PropertyName)
{
case nameof(DataStoreSettingsViewModel.IsDirty):
objIsDirty = o;
++propertyChangedCountIsDirty;
break;
case nameof(DataStoreSettingsViewModel.LocalDatabaseFilePath):
objLocalDatabaseFilePath = o;
++propertyChangedCountLocalDatabaseFilePath;
break;
}
});
// I'd like to replace the above by Moq if shorter/clearer
// Act
if (sutViewModel.FactoryResetCommand.CanExecute(null))
sutViewModel.FactoryResetCommand.Execute(null);
// Assert
Assert.AreEqual(1, propertyChangedCountIsDirty);
Assert.AreEqual(1, propertyChangedCountLocalDatabaseFilePath);
Assert.AreSame(sutViewModel, objIsDirty);
Assert.AreSame(sutViewModel, objLocalDatabaseFilePath);
}
Worked it out myself.
After adding the following interface:
public interface IPropertyChangedEventHandler
{
void PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e);
}
The test using Moq looks like this:
[Test]
[Category("Fast Tests")]
[Category("PropertyChanged Events")]
public void FactoryResetCommand_AllPropertiesChangedInViewModel_PropertyChangedEventsFiredAsExpected()
{
// Arrange
string originalLocalDatabaseFilePath = "oldfp";
string otherLocalDatabaseFilePath = "other" + originalLocalDatabaseFilePath;
Mock<IPropertyChangedEventHandler> mockPropertyChangedEventHandler = new Mock<IPropertyChangedEventHandler>();
Mock<IDataStoreSettingsDataModel> stubDataModel = new Mock<IDataStoreSettingsDataModel>();
stubDataModel.Setup(x => x.LocalDatabaseFilePath).Returns(originalLocalDatabaseFilePath);
IDataStoreSettingsViewModel sutViewModel = new DataStoreSettingsViewModel(
stubDataModel.Object,
ReportExceptionAsync);
sutViewModel.LocalDatabaseFilePath = otherLocalDatabaseFilePath;
sutViewModel.IsDirty = false;
sutViewModel.PropertyChanged += mockPropertyChangedEventHandler.Object.PropertyChanged;
// Act
if (sutViewModel.FactoryResetCommand.CanExecute(null))
sutViewModel.FactoryResetCommand.Execute(null);
// Assert
mockPropertyChangedEventHandler.Verify(x => x.PropertyChanged(sutViewModel,
It.Is<System.ComponentModel.PropertyChangedEventArgs>(e => e.PropertyName == nameof(DataStoreSettingsViewModel.IsDirty))),
Times.Once);
mockPropertyChangedEventHandler.Verify(x => x.PropertyChanged(sutViewModel,
It.Is<System.ComponentModel.PropertyChangedEventArgs>(e => e.PropertyName == nameof(DataStoreSettingsViewModel.LocalDatabaseFilePath))),
Times.Once);
}

Flutter List Value Being Unintentionally Updated

In the code below the print for 'Second Sel Food Date' food date should match 'Initial Sel Food Date', but they don't because 'tempSelected[i].set_eatenDateTime = copyToDate.millisecondsSinceEpoch;' is updating both lists. How can I prevent foodListSelected from being updated? The initial values for foodListSelected are being passed into the class using a stream provider, if that matters.
List<FoodModel> tempSelected = new List();
for (var i = 0; i < foodListSelected.length; i++) {
tempSelected.add(foodListSelected[i]);
}
for (var i = 0; i < tempSelected.length; i++) {
print('Initital Sel Food Date: ' + DateFormat('E-MM-yyyy hh:mm:ss').format(DateTime.fromMillisecondsSinceEpoch(foodListSelected[i].eatenDateTime)));
DateTime eatenDateTime = DateTime.fromMillisecondsSinceEpoch(tempSelected[i].eatenDateTime);
DateTime copyToDate = DateTime(picked.year, picked.month, picked.day, eatenDateTime.hour, eatenDateTime.minute, eatenDateTime.second);
// ISSUE!!!!!
// This is some how setting foodListSelected[i].eatenDateTime as well.
tempSelected[i].set_eatenDateTime = copyToDate.millisecondsSinceEpoch;
tempSelected[i].set_selected = false;
_createFood('eaten_food', tempSelected[i]);
}
}
for (var i = 0; i < foodListSelected.length; i++) {
print('Second Sel Food Date: ' + DateFormat('E-MM-yyyy hh:mm:ss').format(DateTime.fromMillisecondsSinceEpoch(foodListSelected[i].eatenDateTime)));
foodListSelected[i].set_selected = false;
_updateEatenFood(foodListSelected[i]);
}
You are calling a mutator method on the same object which exists in both lists. If you want to create a new object copy for the second list, you should write a method that clones the current object, and use that in your first loop.

Display a chunked items list in Java 8

With the following code:
public class Main {
public static void main(String[] args) {
final List<Integer> items =
IntStream.rangeClosed(0, 23).boxed().collect(Collectors.toList());
final String s = items
.stream()
.map(Object::toString)
.collect(Collectors.joining(","))
.toString()
.concat(".");
System.out.println(s);
}
}
I get:
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23.
What I would like to do, is to break the line every 10 items, in order to get:
0,1,2,3,4,5,6,7,8,9,
10,11,12,13,14,15,16,17,18,19,
20,21,22,23.
I have try a lot of things after googling without any success !
Can you help me ?
Thanks,
Olivier.
If you're open to using a third-party library, the following will work using Eclipse Collections Collectors2.chunk(int).
String s = IntStream.rangeClosed(0, 23)
.boxed()
.collect(Collectors2.chunk(10))
.collectWith(MutableList::makeString, ",")
.makeString("", ",\n", ".");
The result of Collectors2.chunk(10) will be a MutableList<MutableList<Integer>>. At this point I switch from the Streams APIs to using native Eclipse Collections APIs which are available directly on the collections. The method makeString is similar to Collectors.joining(). The method collectWith is like Stream.map() with the difference that a Function2 and an extra parameter are passed to the method. This allows a method reference to be used here instead of a lambda. The equivalent lambda would be list -> list.makeString(",").
If you use just Eclipse Collections APIs, this problem can be simplified as follows:
String s = Interval.zeroTo(23)
.chunk(10)
.collectWith(RichIterable::makeString, ",")
.makeString("", ",\n", ".");
Note: I am a committer for Eclipse Collections.
If all you want to do is process these ascending numbers, you can do it like
String s = IntStream.rangeClosed(0, 23).boxed()
.collect(Collectors.groupingBy(i -> i/10, LinkedHashMap::new,
Collectors.mapping(Object::toString, Collectors.joining(","))))
.values().stream()
.collect(Collectors.joining(",\n", "", "."));
This solution can be adapted to work on an arbitrary random access list as well, e.g.
List<Integer> items = IntStream.rangeClosed(0, 23).boxed().collect(Collectors.toList());
String s = IntStream.range(0, items.size()).boxed()
.collect(Collectors.groupingBy(i -> i/10, LinkedHashMap::new,
Collectors.mapping(ix -> items.get(ix).toString(), Collectors.joining(","))))
.values().stream()
.collect(Collectors.joining(",\n", "", "."));
However, there is no simple and elegant solution for arbitrary streams, a limitation which applies to all kind of tasks having a dependency to the element’s position.
Here is an adaptation of the already linked in the comments Collector:
private static Collector<String, ?, String> partitioning(int size) {
class Acc {
int count = 0;
List<List<String>> list = new ArrayList<>();
void add(String elem) {
int index = count++ / size;
if (index == list.size()) {
list.add(new ArrayList<>());
}
list.get(index).add(elem);
}
Acc merge(Acc right) {
List<String> lastLeftList = list.get(list.size() - 1);
List<String> firstRightList = right.list.get(0);
int lastLeftSize = lastLeftList.size();
int firstRightSize = firstRightList.size();
// they are both size, simply addAll will work
if (lastLeftSize + firstRightSize == 2 * size) {
System.out.println("Perfect!");
list.addAll(right.list);
return this;
}
// last and first from each chunk are merged "perfectly"
if (lastLeftSize + firstRightSize == size) {
System.out.println("Almost perfect");
int x = 0;
while (x < firstRightSize) {
lastLeftList.add(firstRightList.remove(x));
--firstRightSize;
}
right.list.remove(0);
list.addAll(right.list);
return this;
}
right.list.stream().flatMap(List::stream).forEach(this::add);
return this;
}
public String finisher() {
return list.stream().map(x -> x.stream().collect(Collectors.joining(",")))
.collect(Collectors.collectingAndThen(Collectors.joining(",\n"), x -> x + "."));
}
}
return Collector.of(Acc::new, Acc::add, Acc::merge, Acc::finisher);
}
And usage would be:
String result = IntStream.rangeClosed(0, 24)
.mapToObj(String::valueOf)
.collect(partitioning(10));

List and Map in java programing

I need to convert:
List<Map>([{1,2},{2,3}])
To:
List<List>([[1,2],[2,3]])
Can anyone help me with example for this ...
Thanks
I would suggest making a list of specific objects instead of a raw list that the get(0) returns the key and get(1) the value as follows:
List<List<Pair>> convert(List<Map<Integer,Integer> mapList){
List<List<Pair>> listOfList = new ArrayList<List<Pair>>();
for(Map<Integer,Integer> map:mapList){
List<Pair> list = new ArrayList<Pair>();
for(Entry<Integer,Integer> e:map.entrySet()){
list.add(Pair(e.getKey(),e.getValue());
}
listOfList.add(list);
}
return listOfList;
}
class Pair{
Integer first;
Integer second;
//constructor
}
You can try the following Code:
import java.util.*;
class ListOfMapToListOfList
{
public static List<List> toList(List<Map<Integer,Integer>> lList)//method to convert List<Map> to List<List>
{
List<List> list = new ArrayList<List>();
for (int i = 0 ; i < lList.size() ; i++)
{
Map<Integer,Integer> map = lList.get(i);
List<Integer> aList = new ArrayList<Integer>();
Set<Integer> keySet = map.keySet();
for (Integer key : keySet)
{
aList.add(key);
aList.add(map.get(key));
}
list.add(aList);
}
return list;
}
public static void main(String[] args) //main body
{
List<Map<Integer,Integer>> list1 = new ArrayList<Map<Integer,Integer>>();
Map<Integer,Integer> map1 = new HashMap<Integer,Integer>();
map1.put(1,2);
Map<Integer,Integer> map2 = new HashMap<Integer,Integer>();
map2.put(1,2);
list1.add(map1);list1.add(map2);
System.out.println(list1);
System.out.println(toList(list1));//Conversion is done here..and out put is shown.
}
}