Hot questions for Using Mockito in jdbc

Question:

I have to write some unit tests but I have problem with mocking ResultSet and jdbc Connection.

I have this method:

@Test
public void test3() throws SQLException, IOException {

    Connection jdbcConnection = Mockito.mock(Connection.class);
    ResultSet resultSet = Mockito.mock(ResultSet.class);

    Mockito.when(resultSet.next()).thenReturn(true).thenReturn(true).thenReturn(true).thenReturn(false);
    Mockito.when(resultSet.getString(1)).thenReturn("table_r3").thenReturn("table_r1").thenReturn("table_r2");
    Mockito.when(jdbcConnection
            .createStatement()
            .executeQuery("SELECT name FROM tables"))
            .thenReturn(resultSet);

    //when
    List<String> nameOfTablesList = null;
    try {
        nameOfTablesList = Helper.getTablesName(jdbcConnection);
    } catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    //then
    Assert.assertEquals(nameOfTablesList.size(), 3);
}

And error is showing in line executeQuery("SELECT name FROM tables") and it sounds like this:

java.lang.NullPointerException HelperTest.test3(HelperTest.java:71)

Any ideas whats going wrong?


Answer:

You need to create an expectation on jdbcConnection.createStatement().

By default, I believe a null is returned.

Should read something like:

ResultSet resultSet = Mockito.mock(ResultSet.class);
Mockito.when(resultSet.next()).thenReturn(true).thenReturn(true).thenReturn(true).thenReturn(false);
Mockito.when(resultSet.getString(1)).thenReturn("table_r3").thenReturn("table_r1").thenReturn("table_r2");

Statement statement = Mockito.mock(Statement.class);
Mockito.when(statement.executeQuery("SELECT name FROM tables")).thenReturn(resultSet);

Connection jdbcConnection = Mockito.mock(Connection.class);
Mockito.when(jdbcConnection.createStatement()).thenReturn(statement);

Question:

I have a compile problem which is strange. I am not able to fix this. The same peice of code works fine in another project

org.mockito.Mockito.when(jdbcTemplate.query(org.mockito.Matchers.anyString(), 
    org.mockito.Matchers.any(BeanPropertyRowMapper.class))).thenReturn(SOMELIST);

I am getting error as

The method query(String, ResultSetExtractor<T>) in the type JdbcTemplate is not applicable for the arguments (String, BeanPropertyRowMapper)

But When I do this, I do not get any error. But I am not expecting this.

BeanPropertyRowMapper<MyClass> mapper = 
    new BeanPropertyRowMapper<MyClass>(MyClass.class);
org.mockito.Mockito.when(jdbcTemplate.query(org.mockito.Matchers.anyString(), 
    mapper)).thenReturn(SOMELIST);

I am not sure if this is an Eclipse problem. Appreciate your help on this.


Answer:

Since BeanPropertyRowMapper<T> is a generic interface, you should invoke any() like this:

Mockito.when(jdbcTemplate.query(Matchers.anyString(), 
    Matchers.<BeanPropertyRowMapper<MyClass>>any())).thenReturn(SOMELIST);

Question:

I need to create test for this code.

@Autowired
JdbcTemplate jdbcTemplate;

public List<Row> getData(int id) {
    // Preconditions here

    SimpleJdbcCall getCall = new SimpleJdbcCall(jdbcTemplate)
            .withSchemaName(SCHEMA)
            .withProcedureName(SP)
            .declareParameters( 
                // ...
            )
            .returningResultSet("result", (RowMapper<QuestionAnswerRow>) (rs, rowNum) -> .....);

    MapSqlParameterSource params = new MapSqlParameterSource();
    params.addValue("id", id);
    // other parameters here

    Map queryRes = getCall.execute(params);
    List<row> res = (List<row>) queryRes.get("result");
    return res;
}

Could you show me how can I mock here getCall.execute(params) response with Mockito?


Answer:

Your problem here is, that you create the whole getCall object inside your method, which makes it pretty much impossible to somehow inject a mock into that process.

There are a few possibilities here:

a) You can mock your jdbcTemplate and then try to get that to work by mocking all calls that getCall will make to the jdbcTemplate. Since the jdbcTemplate will probably do all the actual db work, this can work, but honestly, it's probably not worth the effort (since it's absolutely non-trivial).

b) You can switch the whole test to an integration-test, letting it run against an in-memory db, for example. Of course, there are many arguments against using an integration test as a substitute for an unit test, so probably this isn't the best way to go, either. It's possible, though, and using the Spring test utils and annotations it can be pretty simple.

c) This leaves us with a bit of work, which in this case means refactoring:

Since your problem is that you create the SimpleJdbcCall internally, one solution would be to to extract that part, for example, into a factory. This simplified example shows that:

@Component
class SimpleJdbcCallFactory {
   public SimpleJdbcCall create(JdbcTemplate template) {
       return new SimpleJdbcCall(template);
   }
}

Now you can add an @Autowired dependency to your class and then mock that depencency in your unit test...

@RunWith(MockitoJUnitRunner.class)
public class YourTestClassHere {

   @Mock
   private SimpleJdbcCallFactory simpleJdbcCallFactory;

   @InjectMocks
   private YourClassHere classToTest;

   @Test
   public void test() {
        SimpleJdbcCall mockedCall = Mockito.mock(SimpleJdbcCall.class);
        Mockito.when( simpleJdbcCallFactory.create(Mockito.any())).thenReturn(mockedCall);
        Mockito.when( mockedCall ).withSchemaName(Mockito.anyString()).thenReturn(mockedCall);
        // etc. unfortunately needed for fluent apis (unless they added those in mockito)
        Mockito.when( mockedCall.execute(Mockito.any()).thenReturn( ... );

        classToTest.getData(123);
   }

}

Question:

I am using Spring boot and Mockito for testing. I have been able to write test cases for Service layer and they re working fine. But, the test cases for DAO layer do not. The jdbcTemplate object that is mocked and autowired gives null pointer when executing the test case. Below are the details:

My DAOTest class:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = EcommerceApplication.class)
public classEcommerceDaoTest {

@InjectMocks
private IEcommerceDao ecommerceDao = new EcommerceDaoImpl();

@Mock
@Autowired
private JdbcTemplate as400JdbcTemplate;

@Before
public void setUp() throws Exception 
{
    MockitoAnnotations.initMocks(this);

}

@Test
public void checkOrderExistsTest() throws EcommerceException{
    Mockito.when(as400JdbcTemplate.queryForObject(queryForOrder,new Object[]
{"1000"}, int.class)).thenReturn(1);
    boolean exists = 
 ecommerceDao.checkOrderExists("1000");
    assertTrue(exists);
}
}

EcommerceDAOImpl.java:

@Override
public boolean checkOrderExists(String orderNo)throws EcommerceException{
boolean doesExist = false;
    int count = 0;
    try{
        count= as400JdbcTemplate.queryForObject(queryForOrder, new Object[]{orderNo}, int.class);
if(count >0){
doesExist = true;
}
    }
catch(Exception e){
}
return doesExist;
}

AS400Config.java:

    @Bean
    @Autowired
    public JdbcTemplate as400JdbcTemplate(@Qualifier("as400DataSource")DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }

ECommerceApplication.java

@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class, 
HibernateJpaAutoConfiguration.class,
    DataSourceTransactionManagerAutoConfiguration.class })
@EnableTransactionManagement
@Import(As400Configuration.class)
public class EcommerceApplication {

public static void main(String[] args) {
    SpringApplication.run(EcommerceApplication.class, args);
}
}

When I am running the test case, I am getting NullPointerException for as400JdbcTemplate. The functionality works fine as is. Its just the test cases for DAO layer that fail because of the inability of the jdbcTemplate to get mocked/autowired.

Please let me know where I am going wrong.


Answer:

  1. You don't need to use @Mock and @Autowired at the same time. Use only @Mock:

    @Mock private JdbcTemplate as400JdbcTemplate;

  2. Use instead of @RunWith(SpringRunner.class) --> @RunWith(MockitoJUnitRunner.class)

Also to inject mock into DAO you can use ReflectionTestUtils from spring test.

public static void setField(Class targetClass, String name, Object value)

@Before
public void setUp() throws Exception {
    MockitoAnnotations.initMocks(this);
    ReflectionTestUtils.setField(ecommerceDao ,"as400JdbcTemplate" , 
      as400JdbcTemplate);

}

@Mock
    private JdbcTemplate as400JdbcTemplate;

Question:

I am trying to use PowerMockito to mock by DBUtil. Unlike typical testcase, I don't want to mock the db calls completely. Whenever Dbutil.getConnection() is called. I want to return the connection object to my local Database.

The simple jdbc connection code below is not working when i call from @BeforeClass method. But it works when I call from the java class.

public static Connection getConnection() throws Exception {
    System.out.println("-------- Connecting to  " + Constants.CONNECTION_STR + "  ------");

    try {
        Class.forName(Constants.ORACLE_DRIVER_NAME);
    } 
    catch (ClassNotFoundException e) {          
        throw new Exception("JDBC Driver not found... " + e);           
    }
    catch (Exception e) {
        // TODO: handle exception
        System.out.println("getConnection :: exp :: "+ e);
    }

    System.out.println("Oracle JDBC Driver Registered Sucessfully!");

    Connection connection = null;

    try {
        connection = DriverManager.getConnection(Constants.CONNECTION_STR, Constants.USERNAME, Constants.PASSWORD);
    } 
    catch (SQLException e) {
        throw new Exception("Connection Failed!",e);                        
    }   

    if (connection != null) {
        System.out.println("Connected to Database Sucessfully, take control your database now!");
        return connection;
    } 

    System.out.println("Failed to make connection!");
    return null;
}

My Testclass

@RunWith (PowerMockRunner.class)
@PrepareForTest(DbUtil.class)
public class MyUtilTest {

@Mock
private DbUtil dbUtil;

@InjectMocks
private MyUtil myUtil;

private static Connection myDBConn;


@BeforeClass
public static void beforeClass() throws Exception {           
    myDBConn = OracleJDBCConnetion.getConnection(); // This always throws invalid username/password exception.
}

@Before
public void setUp() throws Exception {
    MockitoAnnotations.initMocks(this);
}

@Test
public void testIsAdminUser() throws Throwable{


    PowerMockito.mockStatic(DbUtil.class);          
    PowerMockito.when(DbUtil.getConnection()).thenReturn(myDBConn);     

    String accId= "TH123" ;
    boolean  isAdmin = MyUtil.isAdminUser(cloudAccGuid);        
    System.out.println("isAdmin  : " + isAdmin);

    //then
    PowerMockito.verifyStatic(Mockito.times(1));
    DbUtil.getConnection();
    assertTrue(isAdmin);


    //Finally I am closing my connection.
    if(myDBConn!=null &&  !myDBConn.isClosed())
        OracleJDBCConnetion.closeConnection(myDBConn);

}

}

The beforeClass method always throws below expection.

Connection Failed! java.sql.SQLException: ORA-01017: invalid username/password; logon denied

But the same code works, when i try from normal Java class.

Can anyone help in understanding whats wrong here?

I am using ojdbc6.jar and powermokito-1.5.6 and my Oracle database version is 11.2.0.4.0

Thanks.

Edit : I found that @PrepareForTest annotation is causing the error. without the annotation connection is successful but mock does not work. can anyone help me in understanding what is happening? I am very new to these mocking stuff.


Answer:

The problem with @PrepareForTest annotation is, it recursively creates stubs for all dependent classes. Since DBUtil class uses java.sql.Connection class , a stub is created for Connection class also.

So, When i try to create connection, it refers to stub class and throws expection.

Add @PowerMockIgnore annotation to the class,to avoid it. @PowerMockIgnore annotation tells the powermock not to create for the classes that falls under the given package.

@RunWith (PowerMockRunner.class)
@PrepareForTest({DbUtil.class})
@PowerMockIgnore({"java.sql.*"})
public class MyUtilTest {
  ... 
}

This worked for me.

Question:

Please help me to mock below code .Not able to mock getDataSource() which is calling upon JdbcTemplate object.

@Override
public List<AttributeThresholdRange> getThresholdsRangeForXHS(QueryThresholdsRequest queryThresholdsRequest) {

    ArrayOfString attributeGroupIds = queryThresholdsRequest.getAttributeGroupIds();
    Map<String, Object> queryParams = new HashMap<>();
    queryParams.put("groupids", attributeGroupIds.getStrings());

    return new NamedParameterJdbcTemplate(admDatabaseConnector.getJdbcTemplate().getDataSource())
            .query(DBQueryConstants.ADM_QUERY_GET_THRESHOLDS_RANGE_FOR_XHS, 
                    queryParams,
                    new ResultSetExtractor<List<AttributeThresholdRange>>() {
                @Override
                public List<AttributeThresholdRange> extractData(ResultSet resultSet) throws SQLException,DataAccessException  {

                    return null;
                }
            });
}

Answer:

what´s the Mock framework are you using?

If you are using Mockito just Mock the jdbcTemplate and put this method in the when() clause.

when(admDatabaseConnector.getJdbcTemplate().getDataSource())
            .query(anyObject(), anyObject(), anyObject())).thenReturn("Your return queryobject");

You must declare the admDatabaseConnector in the Mock.

Question:

My question is similar to this SO question

I have two JdbcTemplate.queryForObject(..,...,...,) calls in service like below,

depositPostedAmt = jdbcTemplate.queryForObject(Constants.FETCH_DEPOSIT_POSTED_AMT, BigDecimal.class,new Object[] { remitBean.getDepositId() });

and

claimPostedAmt =jdbcTemplate.queryForObject(Constants.FETCH_CLAIM_POSTED_AMOUNT,BigDecimal.class, new Object[] { claim.getClaimId(), remitBean.getContractNum() });

Third argument, new Object[] is different among those two calls and actual sql String differs. So I am trying to use to different mockings to return two different objects in both scenario as shown below ,

when(jdbcTemplate.queryForObject(eq(Constants.FETCH_DEPOSIT_POSTED_AMT), eq(BigDecimal.class), anyObject())).thenReturn(depositPostedAmt);


when(jdbcTemplate.queryForObject(eq(Constants.FETCH_CLAIM_POSTED_AMOUNT), eq(BigDecimal.class), anyObject())).thenReturn(claimPostedAmt);

i.e. I wish to receive two different BigDecimal on two different queries.

I receive depositPostedAmt as expected but claimPostedAmt is always null even though I have initialized it in @Before method same as depositPostedAmt so I am guessing that my when matcher doesn't found any match. I have tried various syntax for third argument matching like any(Object[].class) and anyRef(objectArray) etc but second time, I always get NULL.

I am not sure as what I am missing as there are no errors. I am using JUnit along with Mockito 1.9.5.

Here is sample code - everything works OK except that claimPostedAmt remains null in called service.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestConfig.class, loader = AnnotationConfigContextLoader.class)
public class RCMatchDaoImplTest{

    @Autowired private RCMatchDaoImpl  service;
    @Autowired private JdbcTemplate jdbcTemplate;
    @Autowired private Logger logger;

    private RemitBean remitBean;
    private List<RemitBean> remitBeanList;
    private BigDecimal depositPostedAmt,claimPostedAmt,remitAmount;
    private ClaimVO claim;
    private List<ClaimVO> claims;


    @Before
    public void setUp() throws NoSuchFieldException, SecurityException, Exception{
        /* Set dependencies*/
        service.setJdbcTemplate(jdbcTemplate);
        setFinalStatic(RCMatchDaoImpl.class.getDeclaredField("logger"),logger);

        remitBean = new RemitBean();
        remitBeanList=new ArrayList<>();
        claim= new ClaimVO();
        claims= new ArrayList<>();

        remitBeanList.add(remitBean);
        depositPostedAmt=new BigDecimal(-10);
        claimPostedAmt = new BigDecimal(-10);
        remitAmount=new BigDecimal(20);
        claims.add(claim);
    }

    private static void setFinalStatic(Field field, Object newValue) throws Exception{
        field.setAccessible(true);        
        Field modifiersField = Field.class.getDeclaredField("modifiers");
        modifiersField.setAccessible(true);
        modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
        field.set(null, newValue);
    }

    @Test
    public void testLucenePost_refund_success() throws SQLException{

        /* Set Data */
        remitBean.setRemitType("R");
        remitBean.setRemitAmt(remitAmount);
        remitBean.setDepositId(6866418);
        remitBean.setClaims(claims);

        depositPostedAmt=depositPostedAmt.add(new BigDecimal(20));
        claimPostedAmt=claimPostedAmt.add(new BigDecimal(10));

        claim.setClaimId(6866418);
        claim.setContractNum("100");

         Object[] depositParams = new Object[] { 6866418 };
         Object[] claimParams = new Object[] { 6866418,"100" };

        /* Record Invocations*/

        when(jdbcTemplate.queryForObject(eq(Constants.FETCH_DEPOSIT_POSTED_AMT), eq(BigDecimal.class), anyObject())).thenReturn(depositPostedAmt);
        when(jdbcTemplate.queryForObject(eq(Constants.FETCH_CLAIM_POSTED_AMOUNT), eq(BigDecimal.class), anyObject())).thenReturn(claimPostedAmt);
        doNothing().when(logger).error(anyString());

        /* Play the Service */
        service.lucenePost(remitBeanList);

        /* Verify Results */

        /* reset data to original value as in SetUp method*/
    }

Just for sake of completeness, here is my context class too,

import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.slf4j.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;



@Configuration
public class TestConfig {

    @Mock JdbcTemplate jdbcTemplate;
    @Mock Logger logger;

    TestConfig(){
        MockitoAnnotations.initMocks(this); 
    }

    @Bean
    public RCMatchDaoImpl getRCMatchDaoImpl() {
        return new RCMatchDaoImpl();
    }

    @Bean
    public JdbcTemplate jdbcTemplate(){
        return jdbcTemplate;
    }

    @Bean
    public Logger logger(){
        return logger;
    }
}

Answer:

I did use this (with Mockito 1.10.19):

when(jdbcTemplate.queryForObject(eq(Constants.FETCH_DEPOSIT_POSTED_AMT), eq(BigDecimal.class), anyVararg())).thenReturn(depositPostedAmt);
when(jdbcTemplate.queryForObject(eq(Constants.FETCH_CLAIM_POSTED_AMOUNT), eq(BigDecimal.class), anyVararg())).thenReturn(claimPostedAmt);

and that is working as expected. Output:

10
0 

as expected.

Some reading: http://site.mockito.org/mockito/docs/current/org/mockito/ArgumentMatchers.html#anyVararg()


Code used:

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import static org.mockito.Matchers.*;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.when;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = RCMatchDaoImplTest.TestConfig.class, loader = AnnotationConfigContextLoader.class)
public class RCMatchDaoImplTest {

    @Autowired
    private RCMatchDaoImpl service;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private Logger logger;

    private RemitBean remitBean;
    private List<RemitBean> remitBeanList;
    private BigDecimal depositPostedAmt, claimPostedAmt, remitAmount;
    private ClaimVO claim;
    private List<ClaimVO> claims;


    @Before
    public void setUp() throws NoSuchFieldException, SecurityException, Exception {
        /* Set dependencies*/
        service.setJdbcTemplate(jdbcTemplate);
        setFinalStatic(RCMatchDaoImpl.class.getDeclaredField("logger"), logger);

        remitBean = new RemitBean();
        remitBeanList = new ArrayList<>();
        claim = new ClaimVO();
        claims = new ArrayList<>();

        remitBeanList.add(remitBean);
        depositPostedAmt = new BigDecimal(-10);
        claimPostedAmt = new BigDecimal(-10);
        remitAmount = new BigDecimal(20);
        claims.add(claim);
    }

    private static void setFinalStatic(Field field, Object newValue) throws Exception {
        field.setAccessible(true);
        Field modifiersField = Field.class.getDeclaredField("modifiers");
        modifiersField.setAccessible(true);
        modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
        field.set(null, newValue);
    }

    @Test
    public void testLucenePost_refund_success() throws SQLException {

        /* Set Data */
        remitBean.setRemitType("R");
        remitBean.setRemitAmt(remitAmount);
        remitBean.setDepositId(6866418);
        remitBean.setClaims(claims);

        depositPostedAmt = depositPostedAmt.add(new BigDecimal(20));
        claimPostedAmt = claimPostedAmt.add(new BigDecimal(10));


        claim.setClaimId(6866418);

        claim.setContractNum("100");

        Object[] depositParams = new Object[]{6866418};
        Object[] claimParams = new Object[]{6866418, "100"};

        /* Record Invocations*/

        when(jdbcTemplate.queryForObject(eq(Constants.FETCH_DEPOSIT_POSTED_AMT), eq(BigDecimal.class), anyVararg())).thenReturn(depositPostedAmt);
        when(jdbcTemplate.queryForObject(eq(Constants.FETCH_CLAIM_POSTED_AMOUNT), eq(BigDecimal.class), anyVararg())).thenReturn(claimPostedAmt);
        doNothing().when(logger).error(anyString());

        /* Play the Service */
        service.lucenePost(remitBeanList);

        /* Verify Results */

        /* reset data to original value as in SetUp method*/
    }

    @Configuration
    public static class TestConfig {

        @Mock
        JdbcTemplate jdbcTemplate;

        @Mock
        Logger logger;

        TestConfig() {
            MockitoAnnotations.initMocks(this);
        }

        @Bean
        public RCMatchDaoImpl getRCMatchDaoImpl() {
            return new RCMatchDaoImpl();
        }

        @Bean
        public JdbcTemplate jdbcTemplate() {
            return jdbcTemplate;
        }

        @Bean
        public Logger logger() {
            return logger;
        }
    }

    public static class RCMatchDaoImpl {

        public static final Logger logger = LoggerFactory.getLogger(RCMatchDaoImpl.class);

        private JdbcTemplate jdbcTemplate;

        public void setJdbcTemplate(final JdbcTemplate jdbcTemplate) {
            this.jdbcTemplate = jdbcTemplate;
        }

        public void lucenePost(final List<RemitBean> remitBeanList) {
            for (RemitBean remitBean : remitBeanList) {
                System.out.println(jdbcTemplate.queryForObject(Constants.FETCH_DEPOSIT_POSTED_AMT, BigDecimal.class, new Object[]{remitBean.getDepositId()}));
                for (ClaimVO claimVO : remitBean.getClaims()) {
                    System.out.println(jdbcTemplate.queryForObject(Constants.FETCH_CLAIM_POSTED_AMOUNT, BigDecimal.class, new Object[]{claimVO.getClaimId(), remitBean.getContractNum()}));
                }
            }
        }
    }

    public static class RemitBean {

        private String remitType;
        private BigDecimal remitAmt;
        private int depositId;
        private List<ClaimVO> claims;
        private Object contractNum;

        public void setRemitType(final String remitType) {
            this.remitType = remitType;
        }

        public void setRemitAmt(final BigDecimal remitAmt) {
            this.remitAmt = remitAmt;
        }

        public void setDepositId(final int depositId) {
            this.depositId = depositId;
        }

        public int getDepositId() {
            return depositId;
        }

        public void setClaims(final List<ClaimVO> claims) {
            this.claims = claims;
        }

        public List<ClaimVO> getClaims() {
            return claims;
        }

        public Object getContractNum() {
            return contractNum;
        }
    }

    public static class ClaimVO {

        private int claimId;
        private String contractNum;

        public void setClaimId(final int claimId) {
            this.claimId = claimId;
        }

        public int getClaimId() {
            return claimId;
        }

        public void setContractNum(final String contractNum) {
            this.contractNum = contractNum;
        }
    }

    static class Constants {
        public static final String FETCH_DEPOSIT_POSTED_AMT = "1";
        public static final String FETCH_CLAIM_POSTED_AMOUNT = "2";
    }
}

Question:

When I am executing the second test testExecute_noException, still its returning null pointer exception. For first test is returning null pointer exception is valid, but for the second test I need to continue with the next lines tests. Please refer more details in below.


Actual Code:

import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;

public class SimpleQueryExecutorTasklet implements Tasklet {

    private DataSource dataSource;
    private String sql;

    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public void setSql(String sql) {
        this.sql = sql;
    }

    @Override
    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
        new JdbcTemplate(this.dataSource).execute(this.sql);
        return RepeatStatus.FINISHED;
    }
}

Test Code:

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import org.powermock.api.mockito.PowerMockito;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;

@RunWith(MockitoJUnitRunner.class)
public class SimpleQueryExecutorTaskletTest {

    @InjectMocks
    SimpleQueryExecutorTasklet simpleQueryExecutorTasklet;

    @Mock
    StepContribution stepContribution;

    @Mock
    ChunkContext chunkContext;

    @Mock
    JdbcTemplate jdbcTemplate;

    @Mock
    DataSource dataSource;

    String sql="select * from abc;";

    @Before
    public void setUp() throws Exception {
        simpleQueryExecutorTasklet.setDataSource(dataSource);
        simpleQueryExecutorTasklet.setSql(sql);
        PowerMockito.whenNew(JdbcTemplate.class).withAnyArguments().thenReturn(jdbcTemplate);
    }

    @Test(expected = NullPointerException.class)
    public void testExecute() throws Exception {
        simpleQueryExecutorTasklet.execute(stepContribution,chunkContext);
    }

    @Test
    public void testExecute_noException() throws Exception {
     Mockito.doNothing().when(jdbcTemplate).execute(Mockito.any(String.class));
        simpleQueryExecutorTasklet.execute(stepContribution,chunkContext);
        // Here will write some assertions
    }
}

Exception log from Junit execution:

java.lang.NullPointerException
                at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:390)
                at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:428)
                at com.xxxxxx.api.accel.operations.SimpleQueryExecutorTasklet.execute(SimpleQueryExecutorTasklet.java:29)
                at com.xxxxxx.api.accel.operations.SimpleQueryExecutorTaskletTest.testExecute_noException(SimpleQueryExecutorTaskletTest.java:61)
                at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
                at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
                at java.lang.reflect.Method.invoke(Method.java:498)
                at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
                at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
                at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
                at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
                at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
                at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
                at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
                at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
                at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
                at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
                at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
                at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
                at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
                at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
                at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
                at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
                at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
                at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
                at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
                at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
                at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

Answer:

You can try below code

@RunWith(SpringJUnit4ClassRunner.class)
public class DaoImplTests{

    @Autowired
    private Dao dao;

    @Mock
    JdbcTemplate jdbcTemplate;

    @Test
    public void testUsingMockito() {
        try {
            User mockedUserInfo = new User();
            //setters
            mockedUserInfo.setXXX;
            mockedUserInfo.setYYY;

            Mockito.when(((JdbcDaoSupport)dao.getTemplate())).thenReturn(jdbcTemplate);
            Mockito.when(jdbcTemplate.queryForObject(Mockito.anyString(), Mockito.any(Object[].class),
                    Mockito.any(RowMapper.class))).thenReturn(mockedUserInfo);
            User userInfo = dao.getUserInfo("");
            Assert.assertNotNull(userInfo);
            Assert.assertEquals(mockedUserInfo.getXXX(), userInfo.getXXX());
            //few more assertions
        } catch (Exception e) {
            Assert.fail(" : " + e.getMessage());
        }
    }

}

Question:

I wrote a test case but I get a null pointer exception at the return KeyHolder.getKey() line.

My test case looks like this:

@InjectMocks
private UserDAOImpl userDAO;

@Mock
private JdbcTemplate jdbcTemplate;

@Mock
private KeyHolderFactory keyHolderFactory;

@Before
public void setup() {
    MockitoAnnotations.initMocks(this);
    ReflectionTestUtils.setField(userDAO, "jdbcTemplate", jdbcTemplate);
}

@Test
public void testCreateUser() {

    KeyHolder keyHolder = mock(GeneratedKeyHolder.class);

    when(keyHolderFactory.newKeyHolder()).thenReturn(keyHolder);

    User user = getUserInfo();

    Map<String,Object> map = new HashMap<>();
    map.put("id",1L);
    when(keyHolder.getKeys()).thenReturn(map);
    when(keyHolder.getKey()).thenReturn(1L);

    when(jdbcTemplate.update(Mockito.any(PreparedStatementCreator.class), Mockito.any(KeyHolder.class))).thenReturn(1);

    assertEquals(1L, userDAO.createUser(user));
}

And the method looks like this:

 @Override
  public long createUser(User user) {

KeyHolder keyHolder = new GeneratedKeyHolder();

jdbcTemplate.update(connection -> {
  PreparedStatement ps = connection
      .prepareStatement("insert into user (address, first_name,last_name, email, password, phone_number, is_init, is_system_admin, created_at)"
              + " values( ?, ?, ?, ?, ?, ?, ?, ?,?)",
          Statement.RETURN_GENERATED_KEYS);
  ps.setString(1, user.getAddress());
  ps.setString(2, user.getFirstName());
  ps.setString(3, user.getLastName());
  ps.setString(4, user.getEmail());
  ps.setString(5, user.getPassword());
  ps.setString(6, user.getPhone());
  ps.setBoolean(7, user.isActive());
  ps.setBoolean(8, user.isSystemAdmin());
  ps.setDate(9, new Date(Date.from((user.getCreatedAt().toInstant())).getTime()));

  return ps;
}, keyHolder);

return (long) keyHolder.getKey();
  }

I have created an interface KeyHolderFactory:

public interface KeyHolderFactory {
KeyHolder newKeyHolder();
}

And the implementation of this interface is as follows:

public class GeneratedKeyHolderFactory implements KeyHolderFactory {

public KeyHolder newKeyHolder() {
    return new GeneratedKeyHolder();
  }
}

Can someone help me to find a solution?


Answer:

Your issue is next :

In test class you have Mocked bin KeyHolderFactory and this is correct. Then you create mocked KeyHolder, describe it's behavior and make KeyHolderFactory return KeyHolder when it is asked. Everything looks OK except next :

On your code class method you create new KeyHolder using new GeneratedKeyHolder() and this new KeyHolder doesn't relate to those mocked instance that you have in your test class. It is absolutely different objects. That one which is in your test class - is a mock, and will follow your scenario. But that one, in your tested class method, is another object, which of course don't know what to do when you execute keyHolder.getKey().

Solution :

You have injected KeyHolderFactory in your test and well configured it's behavior. Just inject this into your test class as well and use it in your method to create KeyHolder using keyHolderFactory.newKeyHolder() instead of new GeneratedKeyHolder()

Question:

Hi i need help mocking the below statement.

List<String> testString= jdbcTemplate.query(queryString, new Object[] { someStringParameter }, new testMapper());

Answer:

Got this working using the below mock when(jdbcTemplateMock.query(anyString(), Matchers.<Object[]> anyVararg(), Matchers.any(testMapper.class)))

Question:

How do I mock the DriverManager.getConnection() method?

I want to test my method setUpConnectiontoDB()

I tried it with PowerMock, easyMock and Mokito itself. I didn't find anything usefull.

My Code:

import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;

public class MysqlDAO implements DAO {
    private final Properties properties = new Properties();

    public MysqlDAO(String configPath) {
        loadProperties(configPath);
    }

    private Properties loadProperties(String configPath) {
        try {
            properties.load(new FileInputStream(configPath));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return this.properties;
    }

    @Override
    public Connection setUpConnectionToDB() {
        try {
            Class.forName("com.mysql.jdbc.Driver");

            return DriverManager.getConnection(
                    properties.getProperty("url"),
                    properties.getProperty("user"),
                    properties.getProperty("passwd"));

        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
}

Answer:

Some notes on that:

Class.forName("com.mysql.jdbc.Driver");

This line is obsolete since JDBC 4.0. You should be able to run the code without. Or if you think you need it at least abstract it as well to do

Class.forName(properties.getProperty("dbdriver", "com.mysql.jdbc.Driver");

Once that's been taken care of, who says you have to mock it? It's much easier to actually run it.

You could just as well use an in memory database (like h2) for testing and check your code for that. All you'd change would be your url, user and passwd properties.

This would be some example properties for use with h2:

dbdriver = org.h2.Driver
url = jdbc:h2:mem:test
user = sa
passwd = sa

That way, you not only take care of your unit-test for setUpConnectionToDB() but could later use that connection for methods that expect some data in that database.

Question:

I am new to Mockito and trying to cover following source code:

jdbcOperations.update(insertRoleQuery,new Object[]{"menuName","subMenuName","subSubMenuName","aa","bb","cc","role"});

In this query is taking 7 string parameters. I have written the mockito test case for the code and it's also covering the source code but I am not sure whether it's the correct way or not.

when(jdbcOperations.update(Mockito.anyString(), new Object[]{Mockito.anyString(),Mockito.anyString(),Mockito.anyString(),Mockito.anyString(),Mockito.anyString(),Mockito.anyString(),Mockito.anyString()})).thenThrow(runtimeException);

Please suggest if i am doing it right way or not.

Thanks


Answer:

As per the docs, you can either use exact values, or argument matchers, but not both at the same time:

Warning on argument matchers:

If you are using argument matchers, all arguments have to be provided by matchers.

If you do mix them, like in your sample, mockito will complain with something similar to

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
Invalid use of argument matchers!
2 matchers expected, 1 recorded:
-> at MyTest.shouldMatchArray(MyTest.java:38)

This exception may occur if matchers are combined with raw values:
    //incorrect:
    someMethod(anyObject(), "raw String");
When using matchers, all arguments have to be provided by matchers.
For example:
    //correct:
    someMethod(anyObject(), eq("String by matcher"));

For more info see javadoc for Matchers class.

In your case you don't seem to care about the array contents, so you can just use any():

when(jdbcOperation.update(anyString(), any())).thenThrow(runtimeException);

If you want to at least check the number of parameters, you can use either

when(jdbcOperation.update(anyString(), argThat(array -> array.length == 7))).thenThrow(runtimeException);
when(jdbcOperation.update(anyString(), argThat(arrayWithSize(7)))).thenThrow(runtimeException);

If you're interested in matching certain values, you can use AdditionalMatchers.aryEq(expectedArray), or just Mockito.eq(expectedArray) which has a special implementation for arrays, but I fell that the first one expresses your intent in a clearer way.

when(jdbcOperation.update(anyString(), aryEq(new Object[]{"whatever"}))).thenThrow(runtimeException);

Question:

I'm writing a test case for Email DAO layer. which is something like:

@Repository
@PropertySource({ "classpath:/query.properties" })
public class DaoLayerImpl implements DaoLayerDao {

    /** The jdbc template. */
    @Qualifier("mariaJdbcTemplate")
    @Autowired
    private JdbcTemplate jdbcTemplate;

    /** The find staged query. */
    @Value("${someQuery}")
    String someQuery;

    @Override
    public List<SomeBean> getData() throws MariaDbException {

        List<SomeBean> listOfData = new ArrayList<>();
        try {
            listOfData = jdbcTemplate.query(someQuery,
                    new BeanPropertyRowMapper<SomeBean>(SomeBean.class));
        } catch (RuntimeException e) {
            logger.error("RuntimeException in ", e);
        }

        return listOfData;
    }
}

The Test case for this layer is :

@RunWith(SpringRunner.class)
@ActiveProfiles("test")
@PropertySource("classpath:application-test.properties")
public class EmailDaoLayerTest {

    @MockBean
    JdbcTemplate jdbcTemplate;

    @InjectMocks
    DaoLayerImpl dao;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        jdbcTemplate = Mockito.mock(JdbcTemplate.someQuery);
        ReflectionTestUtils.setField(dao, "jdbcTemplate", jdbcTemplate);

    }

    @Test
    public void testCaseForGetData() throws Exception {
        List<SomeBean> beanObject = new ArrayList<>();
        beanObject.add(new SomeBean());
        beanObject.add(new SomeBean());
        beanObject.add(new SomeBean());

        System.out.println(beanObject.size()); // 3

        when(jdbcTemplate.query("someQuery",
                new BeanPropertyRowMapper<SomeBean>(SomeBean.class))).thenReturn(beanObject);


        List<SomeBean> obj = dao.getData();

        System.out.println(obj.size()); //0

        System.out.println("Done");

    }

}

After mocking the object size comes out to be 0 instead of 3. The size of the object before returning is 3. when i actually hitted the DAO, the size of the object comes out to be 0, whereas i had already mocked the jdbc template using when-then .

What is the correct way to mock Bean Property Row Mapper class?


Answer:

Let me answer the question and then criticize your approach, maybe it will help to better understand how the solution should look like at the end.

So to answer your question:

Technically you can probably do something like:

import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.any;
...
Mockito.when(jdbcTemplate.query(eq("someQuery"), 
any(BeanPropertyRowMapper.class)).thenReturn(....);

However, you should ask yourself what exactly are you trying to test here? You have a relatively expensive integration test here that runs the Spring Context (it works with SpringRunner) and creates many objects under the hood.

However based on the method to be tested - I don't see that there is any "meaningful" (subject to tests) code to be tested. You could test that given the query, the BeanPropertyRowMapper indeed can convert the response to instances of SomeBean but then again you mock it and it doesn't really run.

You could check that the query you've prepared runs against the Database and returns the expected results, but it doesn't seem that you prepare any database here.

So If the purpose is coverage - then yes you will be covered, but the tests are not about the coverage, but about making you "sure" that your code works properly. In this case, running the Spring Driven integration Test (with application context and everything) seems to be a huge overkill, MockitoRunner could do the job

Question:

I am new for Junit and Mockito and i am not understand how to write test case for below JdbcTemplate and i tried but getting exception ,Can some one help me please

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
Invalid use of argument matchers!
Code
@Repository
public class BaaisnEvcIdMSRepository {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Transactional
    public RowMapperServerResponse getQueryEvcidRepository(BaaisnEvcIdRequest baaisnEvcIdRequest) {
        RowMapperServerResponse rowMapperServerResponse =  jdbcTemplate.queryForObject(
            "select * from Master_Circuit WHERE master_ckt_id =  ( select max(master_ckt_id)  from master_circuit  WHERE product = ? AND id_type = ?)",
            new Object[]{baaisnEvcIdRequest.getProduct_type(),baaisnEvcIdRequest.getLata()}, new BaaisnRowMapper());
        return rowMapperServerResponse;
    }
}
test class
public class BaaisnEvcIdMSRepositoryTest {

    @InjectMocks
    BaaisnEvcIdMSRepository baaisnEvcIdMSRepository;

    @Mock
    JdbcTemplate jdbcTemplate;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void getQueryEvcidRepositoryTest() {


          when(jdbcTemplate.queryForObject(eq(ArgumentMatchers.anyString()), refEq(new Object[]{ArgumentMatchers.anyInt()}), eq(String.class))).thenReturn("data");

          verify(jdbcTemplate, times(1)).queryForObject(eq(ArgumentMatchers.anyString()), refEq(new Object[]{ArgumentMatchers.anyInt()}), eq(String.class));

    }

}

Answer:

The InvalidUseOfMatchersException is coming from your use of eq(ArgumentMatchers.anyString()) and refEq(new Object[]{ArgumentMatchers.anyInt()}). You are not supposed to wrap ArgumentMatchers inside anything else.

You also seem to aim at the wrong queryForObject method. It should be this one instead.

As mentioned before you need to call the method under test before doing the verification.

@Test
public void getQueryEvcidRepositoryTest() {

    // use a real `BaaisnEvcIdRequest` object if you can
    BaaisnEvcIdRequest req = Mockito.mock(BaaisnEvcIdRequest.class);
    Mockito.when(req.getProduct_type()).thenReturn(1);
    Mockito.when(req.getLata()).thenReturn(new Object());

    Object[] array = new Object[]{req.getProduct_type(),req.getLata()};

    Mockito.when(jdbcTemplate.queryForObject(Mockito.anyString(), Mockito.eq(array), Mockito.any(RowMapper.class)))
           .thenReturn("data");

    baaisnEvcIdMSRepository.getQueryEvcidRepository(req);

    Mockito.verify(jdbcTemplate, Mockito.times(1))
           .queryForObject(Mockito.anyString(), Mockito.eq(array), Mockito.any(RowMapper.class));
}

Question:

I'm trying to mock (Spring boot, JUnit, Oracle)

jdbcTemplate.execute(CallableStatementCreator, CallableStatementCallback);

public class ExceptionTest
{
  @Autowired
  private SecurityDAOImpl securityDAOImplMock;

  @Mock
  private JdbcTemplate jdbcTemplate;

  @Autowired
  private JdbcTemplate resetJdbcTemplate;

  @Before
  public void init() throws Exception
  {
    securityDAOImplMock = spy(new SecurityDAOImpl());
    MockitoAnnotations.initMocks(this);
  }

  @SuppressWarnings("unchecked")
  @Test(expected = SecurityDAOException.class)
  public void testUpdateProfileException()
  {
    DataAccessException dataAccessException = new DataAccessException("Mock Exception",
        new Exception("Mocked DataAccessException"))
    {
      private static final long serialVersionUID = 1L;
    };
    ReflectionTestUtils.setField(securityDAOImplMock, "jdbcTemplate", jdbcTemplate);
    doThrow(dataAccessException).when(jdbcTemplate).execute(any(), any());
    securityDAOImplMock.isTooManyFailedAttempt("", 7, "", "");
  }

  @After
  public void reset()
  {
    ReflectionTestUtils.setField(securityDAOImplMock, "jdbcTemplate", resetJdbcTemplate);
  }
}

I'm getting the following compile time exception:

The method execute(PreparedStatementCreator, PreparedStatementCallback<Object>) is ambiguous for the type 

on this line

doThrow(securityDAOException).when(jdbcTemplate).execute(any(), any());

How to mock jdbcTemplate.execute(callableStatementCreator, callableStatementCallback).How to make this work?


Answer:

Method JdbcTemplate.execute() is overloaded.

So when you mock it using matcher any() the compiler simply does not know which method you actually mean and throws an error.

To fix that supply a class in the matcher to resolve this ambiguity.

For example, if you want to mock

JdbcTemplate.execute(PreparedStatementCreator psc, PreparedStatementCallback<T> action)

use

doThrow(securityDAOException).when(jdbcTemplate).execute(any(PreparedStatementCreator.class), any(PreparedStatementCallback.class));

Question:

I am using spring with jdbcTemplate for my app and I want to test DaoImpl class. There is implementation for insertion, updation and retrieval operation

Dao class Method

//dummy class
public class PlayerDAOImpl implements PlayerDAO {

@Autowired
private JdbcTemplate jdbcTemplate;


public Integer getPlayer(int playerId) {

    String sql = "SELECT ccount(1) FROM PLAYER WHERE 
     PLAYER_ID = ?";
     return  (jdbcTemplate. queryForObject("Query", new Object[]{playerId}, 
  Integer.class)!=0); //here only throws exception

}
//other methods
}

and for that I have written Test class which execute successfully for insertion and updation but while retrieving it is giving nullpointer exception.

 @RunWith(MockitoJUnitRunner.class)
 class Test{
 @InjectMocks
  PlayerDAOImpl dao;
 @Mock
 JdbcTemplate jdbcTemplate;

  @Test
  public void retrieveResult(){

   Mockito.when(dao.getPlayer(int playerId)).thenReturn(false);

   //Assert Statement

  }}

I have googled/tried but not found solution which worked for me. So how to test that method or inject jdbcTemplate so that it will succeed.

Thanks for Help!!


Answer:

The problem is that you are trying to mock the class under test (PlayerDAOImpl) instead of its dependency (JdbcTemplate).

Change you mock to something like:

Mockito.when(jdbcTemplate.queryForObject(Mockito.any(), Mockito.any(), Mockito.any()).thenReturn(COUNT);

Where COUNT is an Integer, and then write your assertions on the return value of dao.getPlayer.

Question:

I'm trying using mockito to mock jdbcTemplate and call the method query passing it parameters using Object[]{}.

I'm making the unit test for my DAO layer I want to mock jdbcTemplate and call the method query and pass the sql string,a RowMapper and parameters using Object[] {}

public List<EntityType> myDaoMethod(Date fechaInicio, Date fechaFin)
            throws NotDataFoundException {
        log.info("entering => myDaoMethod");
        log.info("param => fechaInicio :" +  fechaInicio);
        log.info("param => fechaFin :" +  fechaFin);

        log.debug("Se ejecutando consulta...");
        try {

            List<EntityType> query = jdbcTemplate.query(QueryStrs.MY_QUERY,
                    new Object[] {fechaInicio, fechaFin},
                    new BeanPropertyRowMapper<EntityType>(EntityType.class));
            log.debug("Se ejecuto consulta. ");

            return query;
        }catch(DataAccessException e) {
            log.error("No se encontro informacion en la consulta myDaoMethod (2)", e);
            throw new NotDataFoundException(e);
        }finally {
            log.info("exiting => myDaoMethod");
        }
    }
    @Mock
    private JdbcTemplate jdbcTemplate;

        @Test
    public void myTestMethod() throws NotDataFoundException {

        List<EntityType> listValue = new ArrayList<>();

        listValue.add(new EntityType((short) 2, "modem 2"));
        listValue.add(new EntityType((short) 1, "modem"));

        when(jdbcTemplate.query(any(String.class),any(Object[].class), any(BeanPropertyRowMapper.class))).thenReturn(listValue);

        MyDao dao = new MyDaoImpl(jdbcTemplate);
        List<EntityType> otrasAdicionalesPorRangoFecha = dao.myDaoMethod(any(Date.class), any(Date.class));

        Assert.assertNotNull(otrasAdicionalesPorRangoFecha);
        Assert.assertTrue(!otrasAdicionalesPorRangoFecha.isEmpty());
//      Assert.assertArrayEquals(listValue.toArray(), otrasAdicionalesPorRangoFecha.toArray());

    }

The trace result is

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: Invalid use of argument matchers! 3 matchers expected, 2 recorded: -> at com.oracle.reporter.tddtest.rrhhcomision.OtrasAdicionalesDaoTest.testBuscarOtrasAdicionalesPorFecha(OtrasAdicionalesDaoTest.java:80) -> at com.oracle.reporter.tddtest.rrhhcomision.OtrasAdicionalesDaoTest.testBuscarOtrasAdicionalesPorFecha(OtrasAdicionalesDaoTest.java:80)

This exception may occur if matchers are combined with raw values: //incorrect: someMethod(anyObject(), "raw String"); When using matchers, all arguments have to be provided by matchers. For example: //correct: someMethod(anyObject(), eq("String by matcher"));


Answer:

The problem is that your dao is not a mocked object, so you are not supposed to pass matchers at this point.

Wrong:

dao.myDaoMethod(any(Date.class), any(Date.class));

Correct:

dao.myDaoMethod(new Date(1), new Date(2));

Question:

I want to know how to mock the particular code using Mockito:

List<Map<String, Object>> list = jdbcTemplate.queryForList(
    sqlQuery, 
    new Object[] { inflowId }
);

I tried the following code:

Mockito.doReturn(list)
       .when(jdbcTemplate)
       .queryForList(Mockito.anyString(), Mockito.any(Class.class));

and:

when(
    jdbcTemplate.queryForList(Mockito.anyString(), Mockito.any(Object[].class))
).thenReturn(list);

My problem is that particular method is not getting mocked in JUnit. When the method is called, it returns null whereas it should return the list.


Answer:

This should work:

import org.hamcrest.CoreMatchers;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.ArgumentMatchers;
import org.mockito.Mockito;
import org.springframework.jdbc.core.JdbcTemplate;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class DemoTest {

    @Test
    public void mockJdbcTemplate() {
        JdbcTemplate mockTemplate = Mockito.mock(JdbcTemplate.class);

        List<Map<String, Object>> mockResult = new ArrayList<>();

        Mockito.when(mockTemplate.queryForList(Mockito.anyString(), ArgumentMatchers.<Object>any())).thenReturn(mockResult);
        // Alternatively:
        // when(mockTemplate.queryForList(anyString(), Mockito.<Object>any())).thenReturn(mockResult);

        String query = "some query";
        Object[] params = new Object[]{1};

        List<Map<String, Object>> returnedResult = mockTemplate.queryForList(query, params);

        Assert.assertThat(returnedResult, CoreMatchers.sameInstance(mockResult));
    }

}

The trick is to use ArgumentMatchers.<Object>any() as there are multiple queryForList method implementations and the one we want to mock receives a varargs parameter.

Question:

I can`t find info how to set up separate H2 db for JUnit in servlets. All info about Spring, but i need H2 to test my DAO and controllers in Servlets app. Will be glad about any info.


Answer:

The problem was solved with a bit weird way. In my AuthorService DAO class i created constructor which take a connection. And depends on the situation i inject right connetion with AbstractFactory.

Question:

I try to learn to test my projects correctly and continuously. Unfortunately there are a few things I don‘t understand since there are a lot of different opinions on the topic. What I don’t get is how to decide which classes are „worth“ testing them. As an example I took the example JDBC connection class from oracle:

public Connection getConnection() throws SQLException {
    Connection conn = null;
    Properties connectionProps = new Properties();
    connectionProps.put("user", this.userName);
    connectionProps.put("password", this.password);
    if (this.dbms.equals("mysql")) {
        conn = DriverManager.getConnection(
                   "jdbc:" + this.dbms + "://" +
                   this.serverName +
                   ":" + this.portNumber + "/",
                   connectionProps);
    } else if (this.dbms.equals("derby")) {
        conn = DriverManager.getConnection(
                   "jdbc:" + this.dbms + ":" +
                   this.dbName +
                   ";create=true",
                   connectionProps);
    }
    System.out.println("Connected to database");
    return conn;
}
 

I know I can mock objects to be able to look at the class more isolated. Is it even useful to test a class like this, or can I benefit from doing something like this, to see if a connection could theoretically be made?

public class TestClass {

    @Mock
    private Connection conn;

    @Mock
    private Database database;

    @BeforeEach
    public void setUp() throws Exception {
        assertNotNull(database);
        when(database.getConnection()).thenReturn(conn);
    }
}

Answer:

Mocking in unit tests helps you test the part of your code that would otherwise be using a resource. Using it to test a class where it's only purpose is to establish connection to a resource makes no sense.

This functionality will be tested during an integration testing. See more on integration and unit testing here

Question:

In my Spring Boot project I have two datasources:

    @Primary
    @Bean(name = "pgDatasource")
    public BasicDataSource dataSource() {
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName(env.getProperty("spring.datasource.dbcp2.driver-class-name"));
        dataSource.setUrl(env.getProperty("spring.datasource.dbcp2.url"));
        dataSource.setUsername(env.getProperty("spring.datasource.dbcp2.username"));
        dataSource.setPassword(env.getProperty("spring.datasource.dbcp2.password"));
        dataSource.setMaxActive(Integer.valueOf(env.getProperty("spring.datasource.dbcp2.max-total")));
        dataSource.setMaxIdle(Integer.valueOf(env.getProperty("spring.datasource.dbcp2.max-idle")));
        dataSource.setInitialSize(Integer.valueOf(env.getProperty("spring.datasource.dbcp2.initial-size")));
        return dataSource;
    }

    @Bean(name = "h2Datasource")
    public BasicDataSource h2DataSource() {
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName(env.getProperty("spring.h2.datasource.driver-class-name"));
        dataSource.setUrl(env.getProperty("spring.h2.datasource.url"));
        dataSource.setUsername(env.getProperty("spring.h2.datasource.username"));
        dataSource.setPassword(env.getProperty("spring.h2.datasource.password"));

        Resource initData = new ClassPathResource("scripts/inmem.sql");
        DatabasePopulator databasePopulator = new ResourceDatabasePopulator(initData);
        DatabasePopulatorUtils.execute(databasePopulator, dataSource);

        return dataSource;
    }

Here datasource for PostgreSQL is a primary bean. In my several tests I would like to run a script against h2 database. For that I am trying to use @Sql annotation. However, if I use @Sql, it runs script against pgDatasource. I could configure h2 as a primary bean for those tests, but test methods' bodies are dependent on the configuration where pgDatasource is a primary bean.

Test sample:

@Test
@Sql(scripts = "/clean_login_attempts.sql", executionPhase = AFTER_TEST_METHOD)
void loginAttemptsIncrementTheCount() throws Exception {
    unsuccessfulLoginRequest();
    unsuccessfulLoginRequest();
    unsuccessfulLoginRequest();

    LoginAttempt loginAttempt = loginAttemptService.getAttempt("admin");
    assertEquals(3, loginAttempt.getAttempt());
}

Is it possible to configure datasource for org.springframework.test.context.jdbc.Sql annotation?


Answer:

Adding config = @SqlConfig(dataSource = "h2Datasource", transactionManager = "h2tx") solved the issue.

@Test
@Sql(scripts = "/clean_login_attempts.sql", executionPhase = AFTER_TEST_METHOD, config = @SqlConfig(dataSource = "h2Datasource", transactionManager = "h2tx"))
void loginAttemptsIncrementTheCount() throws Exception {
    unsuccessfulLoginRequest();
    unsuccessfulLoginRequest();
    unsuccessfulLoginRequest();

    LoginAttempt loginAttempt = loginAttemptService.getAttempt("admin");
    assertEquals(3, loginAttempt.getAttempt());
}

Question:

What is the better approach to test springJdbcTemplate using junit and mockito. How to mock jdbcTemplate or NamedParameterJdbcTemplate.


Answer:

How to mock jdbcTemplate or NamedParameterJdbcTemplate.

Don't mock them. You want to test that data are correctly inserted in and retrieved from the database. If you mock them, the value of the tests will be weak.

So for your unit tests, just set the datasource to connect to a in-memory database and test the methods you are using.

You can rely on the 3.8.5. Testing data access logic with an embedded databasedocumentation :

Question:

In the test case for service,I am unable to resolve dependency of dao class and JdbcTemplate.

public class TestPromotionUsingJunit {

    @InjectMocks
    private ItemService itemService;

    @Mock
    private ItemDAOImpl itemDAOImpl;
    @Mock
    private JdbcTemplate jdbcTemplate;

    @Before
    public void setupMock() {
        MockitoAnnotations.initMocks(this);

        itemService = new ItemService();

    }

    @Test
    public void testFindMax() {
        Product pro1 = new Product();
        pro1.setPluCode("4900692627408");
        pro1.setCategoryNo("2");
        pro1.setCategoryName("Women");
        pro1.setProductName("T-Shirt10163");
        pro1.setColor("CY");
        pro1.setSize("32");
        BigDecimal b1 = new BigDecimal(94.00);
        BigDecimal b2 = new BigDecimal(8);
        pro1.setPrice(b1);
        pro1.setTax(b2);
        Product pro2 = new Product();
        pro2.setPluCode("4900692627408");

        assertEquals(pro1.getPrice(), itemService.getItem(pro1));

    }

}

Here ItemService should return product object but it returns null. Due to internally unable to solve dependency.


Answer:

@InjectMocks creates a mock instance of itemService, but then

itemService = new ItemService();

creates a real instance and throws the mock away. In setupMock(), after itemService is constructed, try adding the equivalent of this:

itemService.setItemDao(itemDAOImpl);

So you'll have a real ItemService which uses a mock DAO.

Then in testFindMax() configure the DAO to return pro1, something like this:

when(itemDAOImpl.getItem(...)).thenReturn(pro1);