I'm unit testing my dao. I create a list, I add an object to my list and I tell mockito when my method is called, to return my list with a single object. However, when I look at what's returned from my dao method, it's an empty list. I'm not sure what I'm missing.
#InjectMocks
private Dao dao;
#Mock
private JdbcTemplate jdbcTemp;
#Test
public void testGetData() {
List<MyObj> list = new ArrayList<>();
MyObj myObj = new MyObj();
myObj.setMethod("method val");
list.add(myobj);
Mockito.when(jdbcTemp.query(anyString(), Mockito.any(PreparedStatementSetter.class),
Mockito.any(Dao.MyRowMapper.class))).thenReturn(list);
List<MyObj> res = dao.getData(param1, param2); // this is empty, instead of having a value of 1
Assertions.assertThat(res).isNotNull();
}
My Dao class:
public List<MyObj> getData(String arg1, String arg2) {
List<MyObj> list = new ArrayList<MyObj>();
try {
list.addAll(jdbcTemp.query(query, new PreparedStatementSetter() {
public void setValues(PreparedStatement pstmt) throws SQLException {
pstmt.setString(PARAM_ONE, arg1);
pstmt.setString(PARAM_TWO, arg2);
}
}, new MyRowMapper()));
} catch (Exception exp) {
}
return list;
}
I actually made a mistake in describing the problem.
I had two jdbcTemplates in my dao.
So the way I resolved it is to use a #Qualifier("jdbcTemplate") when creating a mock jdbctemplate
Related
I have function like following to generate an object of provided type from any payload:
public static <T> Optional<T> generateObject(String payloadJson, Class<T> type) {
T objectPayload = null;
try {
objectPayload = objectMapper.readValue(payloadJson, type);
}catch (IOException e) {
log.info(e.getMessage());
}
return Optional.ofNullable(objectPayload);
}
Had written the test case as follows
#Test
void generateObject() throws Exception {
Mockito.when( eventUtil.generateObject("a", Mockito.any(Class.class)) ).thenReturn( Optional.of("") );
Mockito.<Optional<Object>>when( eventUtil.generateObject("b", Mockito.any(Class.class)) ).thenReturn( Optional.of("") );
Optional<Object> o2 = eventUtil.generateObject("b", Mockito.any(Class.class));
assertEquals( "lol", o2.get() );
Mockito.verify(eventUtil);
}
The test execution is failing on Mockito.when statement with
java.lang.IllegalArgumentException: Unrecognized Type: [null]
**Note: I have tried providing null, another model class and even the parent class itself with thenReturn( Optional.of()) with no luck. Please point me to the correct direction in this case.
As explained Why doesn't Mockito mock static methods?
you cannot mock static method by using mockito.
Anyway I guess your goal is to check if this utility method behave as you expect in case the objectMapper throws exception or just works fine. So you can make the method non static, then you can inject the objectMapper and try something like:
#Test
void objectMapperThrowsException() throws Exception {
ObjectMapper mapper = Mockito.mock(ObjectMapper.class);
EventUtil eventUtil = new EventUtil(mapper);
Mockito.when(mapper.readValue(any(),any())).thenThrow(IOException.class);
Optional<Object> result = eventUtil.generateObject("b", Object.class);
assertTrue(result.isEmpty());
}
and the positive case
#Test
void objectMapperReturnAValidObject() throws Exception {
Object anObject = new Object();
ObjectMapper mapper = Mockito.mock(ObjectMapper.class);
EventUtil eventUtil = new EventUtil(mapper);
Mockito.when(mapper.readValue(any(),any())).thenReturn(anObject);
Optional<Object> result = eventUtil.generateObject("b", Object.class);
assertFalse(result.isEmpty());
assertEquals(anObject, result.get());
}
The best method to test this method is to convert any data type to JSON and call the method to convert to the original one, try to use a helper class or any other data type
public class TargetTest {
#Test
void generateObject() throws Exception {
// Arrange
ObjectMapper mapper = new ObjectMapper();
Helper helper = new Helper();
helper.setName("test");
String json = mapper.writeValueAsString(helper );
// Act
Helper actual = EventUtil.generateObject(json, Helper.class);
// Assert
}
class Helper {
private String name;
// Getter and setter
}
}
, If you want to mock it, try to use PowerMockito
I've three queries which is
SELECT NAME FROM EMP WHERE EMPID=100; // THIS RETURNS A STRING
SELECT DEPTID FROM EMP WHERE EMPID=100; // THIS RETURNS AN INT
SELECT EMPID FROM DEPT WHERE DEPTID=101; // THIS RETURNS A LIST
Now I'm trying to write a generic code to return the object, but however I'm able to send only one type i.e. list of object at a high level. Is it possible to send result as it is based on the type?
Here is my code
public Object getObjectFromDB(final String query, final Map<Object, Object> inputMap, JdbcTemplate jdbcTemplate, final Object returnType) throws Exception {
final List<Object> obj = new ArrayList<Object>();
try {
jdbcTemplate.query(new PreparedStatementCreator() {
#Override
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
return con.prepareStatement(query);
}
}, new PreparedStatementSetter() {
#Override
public void setValues(PreparedStatement ps) throws SQLException {
}
}, new ResultSetExtractor<Object>() {
#Override
public Object extractData(ResultSet rs) throws SQLException,DataAccessException {
while(rs.next()) {
if(returnType instanceof Integer) {
obj.add(rs.getInt(1));
break;
} else if(returnType instanceof String) {
obj.add(rs.getString(1));
break;
} else if(returnType instanceof List) {
obj.add(rs.getObject(1));
}
}
return obj;
}
});
} catch (Exception e) {
LOG.error(e);
}
return obj;
}
It always returns obj which is a list object even though if I want to trigger first query. Any ideas would be appreciated.
Have you tried writing a generic method? See Generic Methods for more info. This could easily work if you already know the return type you are expecting for any particular set of parameters that you pass to your method.
This post describes how to write a method with generic return type.
One possible function protoype can be :
public static <T> List<T> getObjectFromDB(final String query, final Map<Object, Object> inputMap, JdbcTemplate jdbcTemplate, T returnType){
}
It will always return a List<Object> as you are declaring it here
final List<Object> obj = new ArrayList<Object>();
try to check the first element of obj (as it's a list) and its type.
I would like to perform a JUnit Parametrized test with data being external.
I have a list of objects and just need to know how I can convert that to a collection of object arrays. I see the below stack overflow question, but I want to add data from a file which is read from my method.
Parameterized JUnit tests with non-primitive parameters?
Working code: something like this:
#RunWith(Parameterized.class)
public class sampletest {
private BranchMailChildSample branch;
public sampletest(BranchMailChildSample branch)
{
this.branch = branch;
}
#Parameters
public static Collection<Object[]> data()
{
String excel = "C:\\Resources\\TestData\\ExcelSheets\\BranchMail\\branchmail_TestData.xlsx";
ExcelMarshallerTool tool = new ExcelMarshallerTool(excel);
List<BranchMailChildSample> items = tool.unmarshallExcel(BranchMailChildSample.class);
//RIGHT HERE I NEED HELP: Convert list to Collection<Object[]>
//return items as Collection of object arrays
}
#Test
public void test()
{
System.out.println(branch.toString());
}
}
You don't have to convert the list.
#RunWith(Parameterized.class)
public class SampleTest {
#Parameters(name = "{0}")
public static List<BranchMailChildSample> data() {
String excel = "C:\\Resources\\TestData\\ExcelSheets\\BranchMail\\branchmail_TestData.xlsx";
ExcelMarshallerTool tool = new ExcelMarshallerTool(excel);
return tool.unmarshallExcel(BranchMailChildSample.class);
}
#Parameter(0)
public BranchMailChildSample branch;
#Test
public void test() {
System.out.println(branch.toString());
}
}
I used field injection, because it needs less code than constructor injection. Setting the name to the object under test prints more helpful output. Please have a look at the documentation of the Parameterized runner.
You can use constructor injection if you don't like the public field.
#RunWith(Parameterized.class)
public class SampleTest {
#Parameters(name = "{0}")
public static List<BranchMailChildSample> data() {
String excel = "C:\\Resources\\TestData\\ExcelSheets\\BranchMail\\branchmail_TestData.xlsx";
ExcelMarshallerTool tool = new ExcelMarshallerTool(excel);
return tool.unmarshallExcel(BranchMailChildSample.class);
}
private final BranchMailChildSample branch;
public SampleTest(BranchMailChildSample branch) {
this.branch = branch;
}
#Test
public void test() {
System.out.println(branch.toString());
}
}
That's why I would suggest you to use TestNG instead if possible.
It's work the same as JUnit but you can use a internal or external DataProvider, execute methods at a given order... It is much more convenient to use
//This method will provide data to any test method that declares that its Data Provider
//is named "test1"
#DataProvider(name = "test1")
public Object[][] createData1() {
return new Object[][] {
{ "Cedric", new Integer(36) },
{ "Anne", new Integer(37)},
};
}
//This test method declares that its data should be supplied by the Data Provider
//named "test1"
#Test(dataProvider = "test1")
public void verifyData1(String n1, Integer n2) {
System.out.println(n1 + " " + n2);
}
I got it to work doing this:
List<BranchMailChildSample> items = tool.unmarshallExcel(BranchMailChildSample.class);
Collection<Object[]> data = new ArrayList<Object[]>();
for(BranchMailChildSample item : items)
{
Object[] objItem = new Object[] { item };
data.add(objItem);
}
return data;
Actually, if you use JUnit 4.12 and the theories runner, something like this should just work:
#RunWith(Theories.class)
public class MyTest
{
#DataPoints public static List<MyClass> myFunctionThatReturnsTestData()
{
// TODO
}
#Theory
public void canDoTheThing(MyClass m) throws Exception {
I have a problem when trying to match an array that is passed as a parameter to a method that receives a varargs array.
The anyVararg() matcher that is mentioned in other questions/answers doesn't work for me because I want to make sure the provided array is the one I need.
I reduced the problem to this example which is easier to understand and abstracts the problem (my real issue is production code and has busines logic so it would be confusing for the purpose of this question):
#RunWith(MockitoJUnitRunner.class)
public class UnitTest {
private Object[] objectArray;
private List<Object> expected;
private TestTarget target;
#Before
public void setUp() {
objectArray = new Object[]{ new Object() };
expected = Arrays.asList(new Object(), new Object());
target = Mockito.spy(new TestTarget());
}
#Test
public void testMakeList() { // this pass as eq works well with normal array
doReturn(expected).when(target).toList(Mockito.eq(objectArray));
Assert.assertEquals(expected, target.makeList(objectArray));
}
#Test
public void testMakeList1() { // this one fails as eq is not working with varargs
doReturn(expected).when(target).toList1(Mockito.eq(objectArray));
Assert.assertEquals(expected, target.makeList1(objectArray));
}
#Test
public void testMakeListWithAryEq() { // fails, aryEq is not working with varargs
doReturn(expected).when(target).toList1(AdditionalMatchers.aryEq(objectArray));
Assert.assertEquals(expected, target.makeList1(objectArray));
}
private class TestTarget {
public List<Object> makeList(Object[] objects) {
return toList(objects);
}
public List<Object> makeList1(Object[] objects) {
return toList1(objects);
}
protected List<Object> toList(Object[] objs) {
return null; // Not implemented "Intentionally"
}
protected List<Object> toList1(Object... objs) {
return null; // Not implemented "Intentionally"
}
}
}
When I run the test cases in the class, the first test case will pass but not the other two, neither using eq nor using aryEq. Showing the following trace:
java.lang.AssertionError: expected:<[java.lang.Object#56d5e457, java.lang.Object#7482384a]> but was:<null>
at org.junit.Assert.fail(Assert.java:88)
at org.junit.Assert.failNotEquals(Assert.java:743)
at org.junit.Assert.assertEquals(Assert.java:118)
at org.junit.Assert.assertEquals(Assert.java:144)
...
This happens because the eq matcher is not working with varargs arrays, is there any alternative to the eq matcher for this use case?
Ok, I think the answer here requires a custom built matcher, which can be implemented in your unit test as so:
private class MyVarargMatcher extends ArgumentMatcher<Object[]> implements VarargMatcher {
private Object[] expectedValues;
MyVarargMatcher(Object... expectedValues) {
this.expectedValues = expectedValues;
}
#Override
public boolean matches(Object varargArgument) {
return new EqualsBuilder()
.append(expectedValues, varargArgument)
.isEquals();
}
}
Then, in testMakeList1() change the first line to this:
Mockito.doReturn(expected).when(target).toList1(Mockito.argThat(new MyVarargMatcher(objectArray)));
Sources:
How to properly match varargs in Mockito
http://maciejmadej.blogspot.com/2011/11/capturing-varargs-argument-using-custom.html
This is no problem with matching varargs. The only limitation is that you have to specify each individual array entry as a matched argument. I have updated your code below to show what I mean. I created a second objectArray2 to make the point clearer. All tests pass:
#RunWith(MockitoJUnitRunner.class)
public class UnitTest {
private Object[] objectArray;
private Object[] objectArray2;
private List<Object> expected;
private TestTarget target;
private Object obj,obj2;
#Before
public void setUp() {
obj = new Object();
obj2 = new Object();
objectArray = new Object[]{ obj };
objectArray2 = new Object[]{ obj, obj2 };
expected = Arrays.asList(new Object(), new Object());
target = Mockito.spy(new TestTarget());
}
#Test
public void testMakeList() { // this pass as eq works well with normal array
doReturn(expected).when(target).toList(Mockito.eq(objectArray));
Assert.assertEquals(expected, target.makeList(objectArray));
}
#Test
public void testMakeList1() { // since objectArray has one entry you need to add one matching argument
doReturn(expected).when(target).toList1(Mockito.eq(obj));
Assert.assertEquals(expected, target.makeList1(objectArray));
}
#Test
public void testMakeListWithAryEq() { // since objectArray2 has two entries you need to add two matching arguments
doReturn(expected).when(target).toList1(Mockito.eq(obj),Mockito.eq(obj2));
Assert.assertEquals(expected, target.makeList1(objectArray2));
}
private class TestTarget {
public List<Object> makeList(Object[] objects) {
return toList(objects);
}
public List<Object> makeList1(Object[] objects) {
return toList1(objects);
}
protected List<Object> toList(Object[] objs) {
return null; // Not implemented "Intentionally"
}
protected List<Object> toList1(Object... objs) {
return null; // Not implemented "Intentionally"
}
}
}
I am using mockito as mocking framework. I have a scenerio here, my when(abc.method()).thenReturn(value) does not return value, instead it returns null.
Here is how my class and test looks like.
public class foo(){
public boolean method(String userName) throws Exception {
ClassA request = new ClassA();
request.setAbc(userName);
ClassB response = new ClassB();
try {
response = stub.callingmethod(request);
} catch (Exception e) {
}
boolean returnVal = response.isXXX();
return returnVal;
}
Now follwoing is the test
#Test
public void testmethod() throws Exception{
//arrange
String userName = "UserName";
ClassA request = new ClassA();
ClassB response = new ClassB();
response.setXXX(true);
when(stub.callingmethod(request)).thenReturn(response);
//act
boolean result = fooinstance.lockLogin(userName);
//assert
assertTrue(result);
}
stub is mocked using mockito i.e using #Mock. The test throws NullPointerException in class foo near boolean retrunVal = response.isXXX();
the argument matcher for stub.callingmethod(request).thenReturn(response) is comparing for reference equality. You want a more loose matcher, like this I think:
stub.callingmethod(isA(ClassA.class)).thenReturn(response);
Ensure that your ClassA implements its own equals and that it is correctly implemented.