1

I tried multiple way to execute the store procedure in my Junit test case to test against the out values but unfortunately nothing is working. My Test case:

public class DataTest {

    @Mock
    private static DataSource ds;

    @InjectMocks
    private DataDaoImpl dataDao = new DataDaoImpl();

    @Mock
    private static JdbcTemplate jdbcTemplate;

    @Mock
    private static SimpleJdbcCall viewProc;


    @Before
    public void setUp() throws IOException, InterruptedException {
        MockitoAnnotations.initMocks(this);
        MockMvcBuilders.standaloneSetup(dataDao).build();
    }

    @BeforeClass
    public static void init() throws Exception {
        viewProc = new SimpleJdbcCall(ds).withSchemaName("schema")
                .withProcedureName("viewProc").withoutProcedureColumnMetaDataAccess()
                .declareParameters(new SqlParameter("param1", Types.VARCHAR))
                .declareParameters(new SqlParameter("param2", Types.VARCHAR))
                .returningResultSet("dataModules", Mockito.anyObject());

        jdbcTemplate = new JdbcTemplate(ds);

    }

    @Test
    public void findDataModules() throws Exception {

        String param1 = "abc";
        List<DataObj> md = new ArrayList<DataObj>();


        int size = 3;
        SqlParameterSource in = new MapSqlParameterSource().addValue("param1", "abc").addValue("param2",
                "123");
        Map map = viewProc.execute(in);
        md = (List<DataObj>) map.get("data");
        assertTrue("Expected Data  ", md.size() >= size);


    }

}

My Main class:

@Repository
public class DataDaoImpl implements DataDao {

    protected Logger logger = LoggerFactory.getLogger(getClass());

    @Resource(name = "db")
    private DataSource db;

    private SimpleJdbcCall viewProc;

    private JdbcTemplate jdbcTemplate;

    /**
     * Initialization of Stored Procs and JDBC Template
     * 
     * @throws Exception
     */
    @PostConstruct
    public void init() throws Exception {
        viewProc = new SimpleJdbcCall(db).withSchemaName("schema")
                .withProcedureName("viewProc").withoutProcedureColumnMetaDataAccess()
                .declareParameters(new SqlParameter("param1", Types.VARCHAR))
                .declareParameters(new SqlParameter("param2", Types.VARCHAR))
                .returningResultSet("data", new ViewDataRowMapper());

        jdbcTemplate = new JdbcTemplate(db);

    }

        @Override
    public List<Data> findUniqueDataModules(String p1, String p2) throws Exception {
        List<DataObj> dataModules = new ArrayList<DataObj>();
        try {
            SqlParameterSource in = new MapSqlParameterSource().addValue("param1", p1).addValue("param2",
                    p2);
            Map map = viewUniqueDataModulesByLicense.execute(in);
            dataModules = (List<DataObj>) map.get("data");
        } catch (Exception e) {
            //Hnadel Exception
        }
        return dataModules;
    }

    }

Above code gives exception says datasource is required. I tried Mockito, powerMockito but it returning empty map. There is no exceptions with mock. I am OK with any solution which can pass my test case. Modified naming.

Hitesh Kumar
  • 512
  • 1
  • 8
  • 27

1 Answers1

1

As much as I hate using reflection in testing, I believe it can help you in your case. Here, after initializing, I set the field viewProc to a mock object which you can use in the test. @PostConstruct is a Spring related annotation, so it will not be called while initializing it.

class DataDaoImplTest {

    private DataDaoImpl dataDao;

    @Mock
    private DataSource dataSource;

    @Mock
    private SimpleJdbcCall jdbcCall;

    @BeforeEach
    void setUp() {
        MockitoAnnotations.initMocks(this);
        this.dataDao = new DataDaoImpl(dataSource);
        ReflectionTestUtils.setField(this.dataDao, "viewProc", jdbcCall);
    }

    @Test
    void findUniqueDataModules() throws Exception {
        // given:
        Map<String, Object> map = new HashMap<>();
        map.put("data", Arrays.asList(new DataDaoImpl.DataObj(), new DataDaoImpl.DataObj()));
        // mocks:
        when(jdbcCall.execute(any(SqlParameterSource.class))).thenReturn(map);
        // when:
        List<DataDaoImpl.DataObj> uniqueDataModules = this.dataDao.findUniqueDataModules("a", "b");
        // then:
        assertEquals(2, uniqueDataModules.size());
    }
}

Another solution would be to test the method against a test database, like H2. But it won't be a unit test.

Mansur
  • 1,661
  • 3
  • 17
  • 41
  • Thanks Mensure, 1) I am not initializing dataSource in constructor. 2) We do not have method DataObj(), new DataDaoImpl.DataObj(). – Hitesh Kumar Jun 16 '20 at 09:39
  • I know, but I just tried to create a similar environment not the same. The point is that, you can use reflection to inject the mock object. – Mansur Jun 16 '20 at 09:42
  • Got it, I am trying with it, but it's checking size against what I created. – Hitesh Kumar Jun 16 '20 at 10:12
  • Also please let me know how to deal with global Map, I have to test a method have Map define globally in the class. – Hitesh Kumar Jun 16 '20 at 10:14
  • the assertion is there just for the sake of it. I couldn't think of anything better to assert. As for global map, you can either add to the original question or create a new question, and we'll see. – Mansur Jun 16 '20 at 10:28
  • Thank you Mensur, I create new question https://stackoverflow.com/questions/62412058/junit-mockito-for-global-java-util-map for global map issue – Hitesh Kumar Jun 16 '20 at 15:28