How to mock jdbcTemplate call of DAO class for Junit test

Viewed 36

I have DAO class as below:-

// Here I have a class that creates it's own jdbcTemplate using new // jdbcTemplate(dataSource)

@Repository
public class MyDao {
  @Autowired
  @Qualifier("db2JdbcTemplate)"
  JdbcTemplate jdbcTemplateDB2;
  public int insertTable(Company comp) {
    int ret = 0;
    try {
      ret = this.jdbcTemplateDB2(db2DataSource).update(ïnsert into "+ table_name + "(COL1,COL2,...) values (?,?,?,..)",
           ps-> {
               ps.setString(1, comp.getName);
               .......
             });
      return ret;
    } catch (Exception ex) {
        // log etc
    }
  }
}

My Test class is as below:-

    @RunWith(MockitoJUnitRunner.class)
    public class MyTest {
    
      @Mock 
      JdbcTemplate jdbcTemplateDB2;
    
      Company comp = new Company(); // this is followed by setter fn to set values.
    
      MyDao mydao = Mockito.mock(MyDao.class);
      Mockito.when(((jdbcTemplateDB2.update(any(String.class), 
                                     any(PreparedStatement.class))).thenReturn(2);
      ReflectionUtils.setField(mydao, "jdbcTemplateDB2", jdbcTemplateDB2);
    
      int bVal = mydao.insertTable(cmp);
    
    }
}

iVal is not getting value 2. It is making original update call and returning value like 0/1. Getting UnnecessaryStubbingException. If I make lenient() call the exception goes away but result is same (expected as lenient only removes warning). How to make this stubbing work?

1 Answers

In this line: MyDao mydao = Mockito.mock(MyDao.class); you're creating a mock object, which overrides your actual class'x behavior, but you seem to want to test this very class, so it doesn't make any sense. What you need to do is: create an actual instance of the class and inject mocks into it (you're using ReflectionUtils to do that, but Mockito has it's own, simple mechanism to do that).

@Mock 
JdbcTemplate jdbcTemplateDB2;
// this tells mockito to create the object and inject mocks into it
@InjectMocks
MyDao myDao;

@Test
void test() {
    // define the behavior for the mock
    when(jdbcTemplateDB2.update(...)).thenReturn(2);

    // call the actual method of the tested class object (not a mock)
    int result = myDao.insertTable(...);

    // perform assertions (e.g. verify the result value)
}

Recommended reading: Mockito documentation (very comprehensive, yet simple).

Important note: field injection is discouraged.

Related