Hot questions for Using Mockito in dao

Hot questions for Using Mockito in dao

Question:

I've started to discovered Mockito library and there is a question for which I didn't find the proper answer.

If I have for example such method in my UserDAO class that saves user in database:

public class UserDAO{
...
 public void create(User user) {
        Connection connection = null;
        PreparedStatement pstmt = null;
        ResultSet generatedKeys = null;
        try {

            connection = getConnection();
            pstmt = connection.prepareStatement(INSERT_USER,
                    PreparedStatement.RETURN_GENERATED_KEYS);
            int counter = 1;
            pstmt.setString(counter++, user.getFirstName());
            pstmt.setString(counter++, user.getLastName());
            pstmt.setString(counter++, user.getEmail());
            pstmt.setString(counter++, user.getPassword());
            pstmt.setString(counter++, user.getRole());
            pstmt.setString(counter, user.getLang());

            pstmt.execute();
            connection.commit();
            generatedKeys = pstmt.getGeneratedKeys();

            if (generatedKeys.next()) {
                user.setId(generatedKeys.getInt(Fields.GENERATED_KEY));
            }
        } catch (SQLException e) {
            rollback(connection);
            LOG.error("Can not create a user", e);
        } finally {
            close(connection);
            close(pstmt);
            close(generatedKeys);
        }
    }
  ....
}

How should I test it ?

If I want to test for example a DAO class then I need to create a DataSource mock, Connection mock, ResultSet mock etc ? And so not to test the database itself ?

But what if I want to also test the behavior of dao and database ?

Would you please produce some code samples, links that could be helpful and show best approaches of doing it ?


Answer:

Here is a good start using Mockito to test your UserDAO. This code uses a good amount of the Mockito features, so you can see how to use them. Let me know if you have questions.

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;
import org.junit.runner.RunWith;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import org.mockito.Mock;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.mockito.runners.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class TestUserDAO {

    @Mock
    DataSource mockDataSource;
    @Mock
    Connection mockConn;
    @Mock
    PreparedStatement mockPreparedStmnt;
    @Mock
    ResultSet mockResultSet;
    int userId = 100;

    public TestUserDAO() {
    }

    @BeforeClass
    public static void setUpClass() throws Exception {
    }

    @AfterClass
    public static void tearDownClass() {
    }

    @Before
    public void setUp() throws SQLException {
        when(mockDataSource.getConnection()).thenReturn(mockConn);
        when(mockDataSource.getConnection(anyString(), anyString())).thenReturn(mockConn);
        doNothing().when(mockConn).commit();
        when(mockConn.prepareStatement(anyString(), anyInt())).thenReturn(mockPreparedStmnt);
        doNothing().when(mockPreparedStmnt).setString(anyInt(), anyString());
        when(mockPreparedStmnt.execute()).thenReturn(Boolean.TRUE);
        when(mockPreparedStmnt.getGeneratedKeys()).thenReturn(mockResultSet);
        when(mockResultSet.next()).thenReturn(Boolean.TRUE, Boolean.FALSE);
        when(mockResultSet.getInt(Fields.GENERATED_KEYS)).thenReturn(userId);
    }

    @After
    public void tearDown() {
    }

    @Test
    public void testCreateWithNoExceptions() throws SQLException {

        UserDAO instance = new UserDAO(mockDataSource);
        instance.create(new User());

        //verify and assert
        verify(mockConn, times(1)).prepareStatement(anyString(), anyInt());
        verify(mockPreparedStmnt, times(6)).setString(anyInt(), anyString());
        verify(mockPreparedStmnt, times(1)).execute();
        verify(mockConn, times(1)).commit();
        verify(mockResultSet, times(2)).next();
        verify(mockResultSet, times(1)).getInt(Fields.GENERATED_KEYS);
    }

    @Test(expected = SQLException.class)
    public void testCreateWithPreparedStmntException() throws SQLException {

         //mock
         when(mockConn.prepareStatement(anyString(), anyInt())).thenThrow(new SQLException());


        try {
            UserDAO instance = new UserDAO(mockDataSource);
            instance.create(new User());
        } catch (SQLException se) {
            //verify and assert
            verify(mockConn, times(1)).prepareStatement(anyString(), anyInt());
            verify(mockPreparedStmnt, times(0)).setString(anyInt(), anyString());
            verify(mockPreparedStmnt, times(0)).execute();
            verify(mockConn, times(0)).commit();
            verify(mockResultSet, times(0)).next();
            verify(mockResultSet, times(0)).getInt(Fields.GENERATED_KEYS);
            throw se;
        }

    }
}

Question:

I am looking for information to build unit test for typical DAO methods (find user by username, etc.) and I found several examples using mocks like this one: http://www.christophbrill.de/de_DE/unit-testing-with-junit-and-mockito/

@Test
public void testComeGetSome() {
    // Mock the EntityManager to return our dummy element
    Some dummy = new Some();
    EntityManager em = Mockito.mock(EntityManager.class);
    Mockito.when(em.find(Some.class, 1234)).thenReturn(dummy);

    // Mock the SomeDao to use our EntityManager
    SomeDao someDao = Mockito.mock(SomeDao.class);
    Mockito.when(someDao.comeGetSome(1234)).thenCallRealMethod();
    Mockito.when(someDao.getEntityManager()).thenReturn(em);

    // Perform the actual test
    Assert.assertSame(dummy, someDao.comeGetSome(1234));
    Assert.assertNull(someDao.comeGetSome(4321));
}

There is also a similar one in Lasse Koskela's book using EasyMock instead of Mockito.

The thing is: what are we really testing in these examples? We are basically telling through mocks what object the query should return, and then asserting that in fact it returned the object we told it to return.

We are not testing if the query is correct or if it returns a different object or no objects at all (or even more than one object). We cannot test if it returns null when the object does not exist in the database. This line

Assert.assertNull(someDao.comeGetSome(4321));

works because there is no scripted interaction for that argument, not because the object does not exist.

It looks like we are just testing if the method calls the proper methods and objects (em.find).

What is the point of unit testing this? Are there any good frameworks in Java to quickly set up an in memory database and perform tests with it?


Answer:

Your doubts really make sense. Actually there is no need to test DAO with unit tests in most cases because unit tests deal with one layer, but DAO cooperate with database layer.

This article explains this idea: http://www.petrikainulainen.net/programming/testing/writing-tests-for-data-access-code-unit-tests-are-waste/

Hence we should test DAO and database layer with integration tests. Integration tests take into account both DAO and database layer.

This article will provide your with Spring + Hibernate example: https://dzone.com/articles/easy-integration-testing

Question:

I'm new to Java / Mockito and trying to test a Dao method, specifically an exception condition that catches ParseException and throws SQLException.

Here's the Dao code:

public Template saveTemplate(Template template) throws SQLException {
    logger.debug("Saving template details into the db ", template.getTemplateName());

    SimpleDateFormat dt = new SimpleDateFormat("yyyyy-mm-dd hh:mm:ss");
    Long date = 0L;
    try {
        date = dt.parse(template.getStartTime()).getTime();
    } catch (ParseException e) {
        throw new SQLException("Error while processing date " + template.getTemplateName());
    }

    Long finalDate = date;

My strategy was to mock the SimpleDateFormat.parse() call so that it throws the ParseException, but that's not working. Not even sure that's a good strategy...

First I tried:

@InjectMocks private SimpleDateFormat simpleDateformat;

but that doesn't work because the SimpleDateFormat constructor requires a parameter, and gets the error:

org.mockito.exceptions.base.MockitoException: Cannot instantiate @InjectMocks field named 'simpleDateFormat' of type 'class java.text.SimpleDateFormat'. You haven't provided the instance at field declaration so I tried to construct the instance. However the constructor or the initialization block threw an exception : null

So then I tried this:

@Mock
private SimpleDateFormat simpleDateFormat;
@Test(expected = SQLException.class)
public void test_save_template_date_parse_error() throws ParseException, SQLException {
  initMocks(this);
  Mockito.mockingDetails(simpleDateFormat);
  Mockito.when(simpleDateFormat.parse(anyString(),new ParsePosition(anyInt()))).thenThrow(new ParseException(anyString(),anyInt()));

    Template template = new Template();
    template.setStartTime("2017-01-02 12:12:12");
    template.setTemplateId(1);
    given(jdbcTemplate.getJdbcOperations()).willReturn(jdbcOperations);
    templateDAOImpl.saveTemplate(template);
}

The resulting error isn't helpful to my unpracticed eye:

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
Misplaced or misused argument matcher detected here:

-> at com.macys.etap.ee.dao.TemplateDAOImplTest.test_save_template_date_parse_error(TemplateDAOImplTest.java:77)
-> at com.macys.etap.ee.dao.TemplateDAOImplTest.test_save_template_date_parse_error(TemplateDAOImplTest.java:77)

You cannot use argument matchers outside of verification or stubbing.
Examples of correct usage of argument matchers:
    when(mock.get(anyInt())).thenReturn(null);
    doThrow(new RuntimeException()).when(mock).someVoidMethod(anyObject());
    verify(mock).someMethod(contains("foo"))

This message may appear after an NullPointerException if the last matcher is returning an object 
like any() but the stubbed method signature expect a primitive argument, in this case,
use primitive alternatives.
    when(mock.get(any())); // bad use, will raise NPE
    when(mock.get(anyInt())); // correct usage use

Also, this error might show up because you use argument matchers with methods that cannot be mocked.
Following methods *cannot* be stubbed/verified: final/private/equals()/hashCode().
Mocking methods declared on non-public parent classes is not supported.

So how do I mock this thing and get the error thrown?

Edit: New approach as suggested, mocking Template.getStartTime(): @Test(expected = SQLException.class) public void test_save_template_date_parse_error() throws ParseException, SQLException { initMocks(this); Template templateMock = Mockito.mock(Template.class); Mockito.when(templateMock.getStartTime()).thenReturn("invalid"); Mockito.mockingDetails(templateMock.getStartTime()); Template template = new Template(); template.setStartTime("2017-01-02 12:12:12"); template.setTemplateId(1); given(jdbcTemplate.getJdbcOperations()).willReturn(jdbcOperations); // Fixed per @Daniel Pryden : works now templateDAOImpl.saveTemplate(templateMock); }

And now works with the fix.


Answer:

In my opinion, you don't even need Mockito here, you can simply do the following :

 Template template = new Template();
 template.setStartTime("THIS IS AN INVALID DATE");
 template.setTemplateId(1);
 templateDAOImpl.saveTemplate(template);

And then the SQLException will be thrown.

Question:

I am beyond frustrated because I can't figure this out. I've been over millions of articles and NOTHING is clear on how this is done. I am trying to write a Mockito test just for practice.

I have a spring java app which is getting data from a database.

Here is the applicationContext.xml

<bean id="Lookup" class="com.gd.test.Lookup">
    <property name="AssetClassDao" ref="assetClass" />
</bean>

<bean id="assetClass" class="com.gd.impl.AssetClassImpl">
    <property name="dataSource" ref="dataSource" />
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="org.apache.commons.dbcp.BasicDataSource" />
    <property name="url"
        value="jdbc:sqlserver://ip:port;databaseName=test" />
    <property name="username" value="user" />
    <property name="password" value="pass" />
</bean>

AssetClassDao.java

public interface AssetClassDao {

     public AssetClass getAssetDataById(int id);
}

AssetClassImpl.java

public class AssetClassImpl implements AssetClassDao {

private DataSource dataSource;
AssetClass ac = new AssetClass();

@Override
public AssetClass getAssetDataById(int id) {

    String sql = "select id, name from TABLE where id="
            + String.valueOf(id);

    Connection conn = null;

    try {
        conn = dataSource.getConnection();
        PreparedStatement ps = conn.prepareStatement(sql);

        ResultSet rs = ps.executeQuery();

        while (rs.next()) {
            ac.setASSET_CLASS_ID(rs.getString("id"));
            ac.setASSET_CLASS_NAME(rs.getString("name"));
        }

        rs.close();
        ps.close();
        return ac;

    } catch (SQLException e) {
        e.printStackTrace();
    }

    return ac;
}

public DataSource getDataSource() {
    return dataSource;
}

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

Lookup.java

public class Lookup {

private AssetClassDao assetClassDao;

public void runNameLookup() throws IOException {

    AssetClass byOne = assetClassDao.getAssetDataById(5);

    System.out.println(byOne.toString());

}

public AssetClassDao getAssetClassDao() {
    return assetClassDao;
}

public void setAssetClassDao(AssetClassDao assetClassDao) {
    this.assetClassDao = assetClassDao;
}

}

The query returns "5" as the ID and "Mortgage" as the NAME. For my test that I am writing with Mockito, how does it know which implementation to use?

My test:

public class TestLookup {
@Mock
private AssetClassDao acd;

@Mock
private Lookup al;

@Mock
private AssetClass ac;

@Before
public void setupMock(){
    MockitoAnnotations.initMocks(this);
    acd = mock(AssetClassImpl.class);
}

@Test
public void testDataById(){
    when(acd.getAssetDataById(5)).thenReturn(ac);
    System.out.println(acd.getAssetDataById(5).getNAME());
}
}

How do I test these values properly?!


Answer:

By writing the following statements you are creating a new object of class AssetClass:

AssetClass ac = new AssetClass();

If you are using Spring then you should be injecting this as one of the dependencies as follows:

@Autowired
private AssetClass ac;

You can now mock this dependency out by writing the following in your test class:

@Mock
private AssetClass ac;

Also, you'll have to mock the other dependencies like DataSource, Connection etc. and do something like this:

@Mock
private DataSource dataSource;

@Mock
private Connection conn;

...

Mockito.when(dataSource.getConnection()).thenReturn(conn);

I hope this will provide you some essence of Mockito and how to use it.

Question:

I am trying to mock a DAO class that has a method which returns a list of a specific class.

private List<SpecificClass> getInfo(){

List<SpecificClass> returnInformation = dao.list(ParamOne, Param Two, SpecificClass.class);
}

The dao mentioned in the above method refers to another class.

I begin by mocking that DAO class.

Mockito.mock(TheDaoClass.class);

and creating a mocked list

private @Mock List<SpecificClass> returnedList = new ArrayList<SpecificClass>();

Then I make call to that method

dao.list(ParamOne, Param Two, SpecificClass.class);

and specify what needs to be done when it is called

when(dao.list(ParameterOne, anyString(), SpecificClass.class)).thenReturn(returnedList);

When I do the above I get a null pointer exception. There can be two causes:

I understand the list is empty but all it is supposed is hold SpecificClass's five values but that shouldn't throw an error at this point.

I think object dao is not getting mocked properly. I am only mocking the whole class Mockito.mock(TheDaoClass.class) in order to mock any object asociated with that class. I think that it is not achieving the objective. how do I go about solving this problem? Any help is appreciated. Thanks.


Answer:

Make your mocked DAO object a property of your test class like so:

@Mock
private TheDaoClass mockDaoClass;

Then, in your setUp() method at the beginning of your test class call initMocks:

@BeforeClass
public void setUp() {
    MockitoAnnotations.initMocks(this);
}

This should prevent the NullPointer.

Additionally, I recommend that rather than mock the List object (if you are mocking any Java library data type you are probably doing it wrong), you should create a list and populate it.

List<SpecificClass> list = new ArrayList<SpecificClass>();
list.add(new SpecificClass());

Then return the list from the mocked method.

when(mockDaoClass.list(anyString(), anyString(), SpecificClass.class)).thenReturn(list);

Question:

I have a Spring MVC application. It has Controller, Service and Dao. I would like to test only the Controller and Service by Mocking the DAO layer using Mockito.

My Controller class:

@Controller
@RequestMapping(value="/audit")
public class AuditController {

   @Autowired
   AuditService auditService;

   ...
}

My Service class:

@Service
public class AuditService {

   @Autowired
   AuditDao auditDao;

   ....
}

My Test class:

@RunWith(SptringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"/dispatcher-servlet.xml", "spring-context.xml"})
@WebAppConfiguration
public class AuditControllerTest {

   private MockMvc mockMvc;

   @Mock
   AuditDao auditDao;

   @Autowired
   private WebApplicationContext webApplicationContext;

   @Before
   public void setUp() {
       MockitAnnotations.initMocks(this);
       mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
   }


  @Test
  public void testGetAudit() {

      Mockito.when(auditDao.getAudit(Mockito.any(Long.class))).thenReturn(new Audit(1L));
      mockMvc.perform(get("/audit/{id}", "1")).andExpect(status().isOk());
  }
}

PROBLEM: It performs the call fine by going through autowired controller and Service. However, from the Service the DAO calls are going to a real DAO not the Mocked DAO.

  1. I understand that the DAO is autowired to the real Dao, however I am not sure how to replace that Dao with the Mock one from the Test.

  2. Keeping the Dao in the controller and using @InjectMock to the controller works fine, but I want to keep the Dao in the Service and test only the controller and Service, but mock the Dao alone.

  3. I suspect that this issue is to do with the contexts (web application context and the MockMvc context), however I am not sure how to resolve it.

Any help would be greatly appreciated. Thanks in advance.


Answer:

First I would suggest avoiding Autowired fields and have you class explicitly expose their dependencies via constructor dependencies

Controller class:

@Controller
@RequestMapping(value="/audit")
public class AuditController {
    private final AuditService auditService;

    @Autowired
    public AuditController(AuditService auditService) {
        this.auditService = auditService
    }

    //...
}

Service class:

@Service
public class AuditService {            
    private final AuditDao auditDao;

    @Autowired
    public AuditService(AuditDao auditDao) {
        this.auditDao = auditDao;
    }

    //....
}

I was thinking of something along the line of

@RunWith(SptringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"/dispatcher-servlet.xml", "spring-context.xml"})
@WebAppConfiguration
public class AuditControllerTest {

    private MockMvc mockMvc;

    @Mock
    AuditDao auditDao;

    @InjectMock
    AuditService auditService;

    @Before
    public void setUp() {
        MockitAnnotations.initMocks(this);
        AuditController controller = new AuditController (auditService);
        mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
    }

    @Test
    public void testGetAudit() {

      Mockito.when(auditDao.getAudit(Mockito.any(Long.class))).thenReturn(new Audit(1L));
      mockMvc.perform(get("/audit/{id}", "1")).andExpect(status().isOk());
    }
}

But am uncertain if it will behave as expected when exercised.

Question:

I want to test my DAO methods using Mockito (and PowerMockito if needed), but I don't know how to do this. The biggest problem with calling static method (MySQLDAOFactory.getConnection() in MySQLStationDAO). Can you help me?

I obtain connection this way:

public class MySQLDAOFactory extends DAOFactory {     
        public static Connection getConnection() throws DAOException {
            Connection con = null;
            try {
                con = getDataSource().getConnection();
            } catch (SQLException e) {
                throw new DAOException(Messages.CANNOT_OBTAIN_CONNECTION, e);
            }
            return con;
        }

And here is a DAO method:

public class MySQLStationDAO implements StationDAO {
    @Override
    public List<Station> getAllStations() throws DAOException {
        List<Station> stations = new ArrayList<>();
        Connection con = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            con = MySQLDAOFactory.getConnection();
            stmt = con.createStatement();
            rs = stmt.executeQuery(MySQLQueries.SQL_GET_ALL_STATIONS);
            while (rs.next()) {
                stations.add(extractStation(rs));
            }
        } catch (SQLException e) {
            throw new DAOException(Messages.CANNOT_OBTAIN_ALL_STATIONS, e);
        } finally {
            MySQLDAOFactory.close(con, stmt, rs);
        }
        return stations;
    }

Answer:

  1. JUnit: use @RunWith(PowerMockRunner.class) at the class-level.

    TestNG: make your test class extend PowerMockTestCase.

  2. Use @PrepareForTest(MySQLDAOFactory.class) at the class-level in order to instruct PowerMock to prepare the MySQLDAOFactory class for testing.

  3. Use PowerMockito.mockStatic(MySQLDAOFactory.class) in order to mock all methods of MySQLDAOFactory class.

    It is also possible to use partial mocking:

    PowerMockito.stub(PowerMockito.method(MySQLDAOFactory.class, "getConnection")).toReturn(Mockito.mock(Connection.class));

  4. Use something similar in order to stub getConnection():

    Connection mockConnection = Mockito.mock(Connection.class); Mockito.when(MySQLDAOFactory.getConnection()).thenReturn(mockConnection);

  5. Execute getAllStations() on a real instance of MySQLStationDAO, since you are testing MySQLStationDAO class.

  6. If you want to verify that getConnection() method has been called, use something similar:

    PowerMockito.verifyStatic(); MySQLDAOFactory.getConnection();

    However, please read Mockito.verify(T) javadoc for the reasons why it is recommended either to stub or to verify the invocation, not both.

In general, you may want to consult Mockito docs and PowerMockito docs for more information.

Full example that was created using JUnit 4.11, Mockito 1.9.5 and PowerMock (PowerMockito) 1.5.6 (please be careful with versions, since there is a lot of compatibility issues):

@RunWith(PowerMockRunner.class)
@PrepareForTest(MySQLDAOFactory.class)
public class MySQLDAOFactoryTest {

    private StationDAO stationDAO;

    @Mock
    private Connection mockConnection;

    @Mock
    private Statement mockStatement;

    @Mock
    private ResultSet mockResultSet;

    @Before
    public void setUp() {
        stationDAO = new MySQLStationDAO();
    }

    @Test
    public void testGetAllStations_StatementCreated() throws DAOException, SQLException {
        // given
        PowerMockito.mockStatic(MySQLDAOFactory.class);
        Mockito.when(MySQLDAOFactory.getConnection()).thenReturn(mockConnection);
        Mockito.when(mockConnection.createStatement()).thenReturn(mockStatement);
        Mockito.when(mockStatement.executeQuery(anyString())).thenReturn(mockResultSet);

        // when
        stationDAO.getAllStations();

        // then
        Mockito.verify(mockConnection).createStatement();
    }
}

What is next? Check that executeQuery() method has been called with expected arguments? Test how SQLException is handled? These are reasonable scenarios for unit testing, but what about integration testing? I would recommend DBUnit for this purpose. It puts your test database into a known state between test runs, and allows to verify a returned result against an expected XML dataset.

Question:

I'm just getting into testing of code. I have done unit tests before but haven't really isolated them. So they were more like integration test (indirectly). I want to give Mockito a try and I have added it to my Intellij IDE. But I have no idea of how to actually implement mocking at all. There are examples on their website but I just can't wrap my head around the concept of mocking. I know that one uses mocking to isolate the unit testing to ensure that the errors are in the unit itself and not in a dependency.

I wrote the following:

@Test
public void testChangeMemberReturnsTrue() throws Exception {
    Member tempMem = new Member();
    tempMem.setMemberFirstName("Swagrid");
    tempMem.setMemberLastName("McLovin");
    tempMem.setMemberID("SM666");

    SQLDUMMY.saveMember(tempMem);               //Save member to dummy DB.

    Member checkMem = new Member();
    ArrayList<Member> memArr = SQLDUMMY.getAllMembers();
    for (Member m : memArr) {                   // Look through all saved members
        if (m.equals(tempMem)) {                // If match, save to checkMem
            checkMem = m;
        }
    }
    assertTrue(tempMem.equals(checkMem));            // Make sure they are really equal.

    String newfirstname = "Darius";
    String newlastname = "DunkMaster";
    assertTrue(memhandling.changeMember(tempMem, newfirstname, newlastname));

}

And here is the actual method:

public boolean changeMember(Member mem, String n1, String n2) {
    try {
        ArrayList<Member> memArr = SQLDUMMY.getAllMembers();
        for (Member m : memArr) {
            if (m.equals(mem)) {
                m.setMemberFirstName(n1);
                m.setMemberLastName(n2);
                m.setMemberID(ensureUniqueID(m, m.getMemberID())); //Just a method call to another method in the same class to ensure ID uniqueness.
                return true;
            }
            else {
                return false;
            }
        }
    }
    catch (Exception e) {
        System.out.println("Error4.");
    }
    return false;
}

I'd like to mock the SQLDUMMY (Which I created just to see if my tests would pass at all, which they do.) The SQLDUMMY class looks like this:

public class SQLDUMMY {

private static ArrayList<Member> memberList = new ArrayList<>();
private static ArrayList<Ship> shipList = new ArrayList<>();

public static ArrayList<Member> getAllMembers() {
    return memberList;
}

public static void saveMember(Member m) {
    memberList.add(m);
}

public static void deleteMember(Member memIn) {
    memberList.remove(memIn);
}


public static void saveShip(Ship newShip) {
    shipList.add(newShip);
}

public static ArrayList<Ship> getAllShips() {
    return shipList;
}

public static void deleteShip(Ship s) {
    shipList.remove(s);
}

}

It basically just consists of getters and add/remove for the ArrayLists that act as a contemporary DB storage.

Summary: How can I mock the SQLDUMMY class (DAO), so it is no longer a dependency for the Unit tests?


Answer:

You need to read on how Mockito works. The basic idea is that it extends you class and and overrides all methods and allows you to return what ever you want it too.

Syntax is :

SQLDummy sqlDummy = Mockito.mock(SQLDummy.class);
Mockito.when(sqlDummy.getAllShips()).thenReturn(new ArrayList< Ship >())

Question:

I'm new in unit test, and I'm trying to write some tests for my DAO's. I have followed some tutorials/answers here, but most of them don't apply to my DAO's.

I get this warning when I run the test org.mockito.exceptions.verification.WantedButNotInvoked: Wanted but not invoked: mockConn.prepareStatement();

What is wrong?

private ApprovalConditionDAO approvalConditionDAO;
@Mock
DataSource mockDataSource;
@Mock
Connection mockConn;
@Mock
PreparedStatement mockPreparedStmnt;
@Mock
CallableStatement cs;
@Mock
ResultSet mockResultSet;

@Before
public void setUp() throws SQLException {
    approvalConditionDAO = new ApprovalConditionDAO();
    when(mockDataSource.getConnection()).thenReturn(mockConn);
    when(mockDataSource.getConnection(anyString(),
                                      anyString())).thenReturn(mockConn);
    when(mockConn.prepareStatement(anyString(),
                                   anyInt())).thenReturn(mockPreparedStmnt);
    doNothing().when(mockConn).commit();
    doNothing().when(mockPreparedStmnt).setString(anyInt(), anyString());
    when(mockPreparedStmnt.execute()).thenReturn(Boolean.TRUE);
    when(mockPreparedStmnt.getGeneratedKeys()).thenReturn(mockResultSet);
    when(mockResultSet.next()).thenReturn(Boolean.TRUE, Boolean.FALSE);
}

@Test
public void testCreateWithNoExceptions() throws SQLException {    
   ArrayList<ApprovalConditionBean> actualValues = approvalConditionDAO.getAllApprovalCondition();

    //verify and assert
    verify(mockConn, times(1)).prepareStatement(anyString());
    verify(mockPreparedStmnt, times(1)).execute();
    verify(mockConn, times(1)).commit();
    verify(mockResultSet, times(2)).next();
    verify(mockResultSet, times(1)).getString("ID");
    verify(mockResultSet, times(1)).getString("EIT_CODE");
    verify(mockResultSet, times(1)).getString("FRIST_KEY_TYPE");
    verify(mockResultSet, times(1)).getString("FRIST_KEY_VALUE");
    verify(mockResultSet, times(1)).getString("FRIST_EIT_SEGMENT");
    verify(mockResultSet, times(1)).getString("OPERATION");
    verify(mockResultSet, times(1)).getString("SECOND_KEY_TYPE");
    verify(mockResultSet, times(1)).getString("SECOND_KEY_VALUE");
    verify(mockResultSet, times(1)).getString("SECOND_EIT_SEGMENT");
    verify(mockResultSet, times(1)).getString("APPROVAL_CODE");
}

And this is the Dao that I want to test it.

  public class ApprovalConditionDAO extends AppsproConnection {
Connection connection;
PreparedStatement ps;
CallableStatement cs;
ResultSet rs;
RestHelper rh = new RestHelper();


public ArrayList<ApprovalConditionBean> getAllApprovalCondition() {

 ArrayList<ApprovalConditionBean> approvalConditionList =
     new ArrayList<ApprovalConditionBean>();
 try {
     connection = AppsproConnection.getConnection();
     String query =
         "SELECT * FROM "+" "+getSchema_Name()+".XXX_APPROVAL_CONDITION";
     ps = connection.prepareStatement(query);
     rs = ps.executeQuery();
     while (rs.next()) {
         ApprovalConditionBean approvalConditionBean = new ApprovalConditionBean();
         approvalConditionBean.setId(rs.getString("ID"));
         approvalConditionBean.setEitCode(rs.getString("EIT_CODE"));
         approvalConditionBean.setFirstKeyType(rs.getString("FRIST_KEY_TYPE"));
         approvalConditionBean.setFirstKeyValue(rs.getString("FRIST_KEY_VALUE"));
         approvalConditionBean.setFirstEitSegment(rs.getString("FRIST_EIT_SEGMENT"));
         approvalConditionBean.setOperation(rs.getString("OPERATION"));
         approvalConditionBean.setSecondKeyType(rs.getString("SECOND_KEY_TYPE"));
         approvalConditionBean.setSecondKeyValue(rs.getString("SECOND_KEY_VALUE"));
         approvalConditionBean.setSecondEitSegment(rs.getString("SECOND_EIT_SEGMENT"));
         approvalConditionBean.setApprovalCode(rs.getString("APPROVAL_CODE"));


         approvalConditionList.add(approvalConditionBean);

     }

 } catch (Exception e) {
     //("Error: ");
     e.printStackTrace();
 } finally {
     closeResources(connection, ps, rs);
 }
 return approvalConditionList;

}

And this as my AppsproConnection Calss

     public static Connection getConnection(boolean commit) {
    if (CommonConfigReader.getValue("CONNECTION_TYPE").equalsIgnoreCase("JDBC")) {
        return getJDBCConnection(commit);
    } else {
        return getDSConnection(commit);
    }
}

public static Connection getConnection() {
    if (CommonConfigReader.getValue("CONNECTION_TYPE").equalsIgnoreCase("JDBC")) {
        return getJDBCConnection();
    } else {
        return getDSConnection();
    }
}

Answer:

You didn't call the method you wanted to test from the test method. You don't event have a test object to do so.

class TestClass {
    private MyDao underTest;

    @Before
    public void setUp() throws SQLException {
        underTest = new MyDao();
        // mocking things...
    }
}

And using this test object you have to call the method you actually want to test from a test method.

@Test
public void testCreateWithNoExceptions() throws SQLException {
    // ...

    ArrayList<ApprovalConditionBean> actualValues = underTest.getAllApprovalCondition();

    // assertions
}

If you cannot manipulate how you get the connection from a static class then you can refactor your method to get a connection from another method in the same class.

public ArrayList<ApprovalConditionBean> getAllApprovalCondition() {
    // ...
    connection = getConnection();
    // ...
}

Connection getConnection() {
    return AppsproConnection.getConnection();
}

If you are using like this you can instantiate the test object in a way that you can manage what kind of Connection is returned for tests.

@Before
public void setUp() throws SQLException {
    when(mockConn.prepareStatement(anyString(), anyInt())).thenReturn(mockPreparedStmnt);
    doNothing().when(mockConn).commit();
    doNothing().when(mockPreparedStmnt).setString(anyInt(), anyString());
    when(mockPreparedStmnt.execute()).thenReturn(Boolean.TRUE);
    when(mockPreparedStmnt.getGeneratedKeys()).thenReturn(mockResultSet);
    when(mockResultSet.next()).thenReturn(Boolean.TRUE, Boolean.FALSE);

    underTest = new MyDao(){
        @Override
        public Connection getConnection() {
            return mockConn;
        }
    };
}

We are returning the mocked connection from getConnection. This method is called from the getAllApprovalCondition method. In production it is still providing connection through AppsproConnection.

Question:

I am not able to mock Dao method in spring boot. Please let me know what I am doing wrong in below code. I tried using SpringJUnit4ClassRunner and mock the Dao method. But still, it's going into the Dao method instead of returning the mock value. I also tried with MockitoJUnitRunner but that time not able to call the service method as its getting null value.

@RestController
public class HomeController {

    @Autowired
    HomeSeriveInterface service;

    @Autowired
    HomeDaoImpl homeDao;

    @GetMapping(value="/getData")
    public String Data() {
        System.out.println("Inside Controller");
        List < Map < String, Object >> rows = service.getData();
        return "Hi Yogita" + rows;
    }

}

@Service
public class HomeService implements HomeSeriveInterface{

    @Autowired
    HomeDao dao;

    @Override
    public List<Map<String, Object>> getData() {
        System.out.println("Inside Service");
        return dao.getData();
    }

}

@Repository
public class HomeDaoImpl implements HomeDao{

    @Autowired
     @Qualifier("jdbcTemplate1")
     private JdbcTemplate jdbcTemplate;

    @Override
    public List < Map < String, Object >> getData() {
        System.out.println("Inside Dao");
        List < Map < String, Object >> rows = jdbcTemplate.queryForList("SELECT * FROM COURCES");
        return rows;
    }

}

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class CcdWebApplicationTests {


    @InjectMocks
    @Autowired
    HomeController homeController;

    @Mock
    HomeDao homeDao;

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

    @Test
    public void getDataTest() {
        System.out.println("testing *******");
        List < Map < String, Object >> data = null;
        Mockito.when(homeDao.getData())
        .thenReturn(data);
        System.out.println("2nd *");
        String data2 = homeController.Data();
        System.out.println(data2);

    }

}

Answer:

You don't need @InjectMocks and use @MockBean instead of @Mock:

@Autowired
HomeController homeController;

@MockBean
HomeDao homeDao;

You also do not need this part:

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

Question:

I'm using Mockito for testing my API Service REST, i'm using Spring Framework 4.1.4.RELEASE and Mockito 1.9.5.

I have a multi-brand system for access to unique DAOImpl (With unique for each brand @PersistenceContext(unitname = "emX"), where "X" it's brand char) , each brand extends from abstract DaoBase class (who implemements an interface called Dao) and i access from Service class obtaining the component via:

applicationContext.getBean(qualifier.concat(brand.name()), clazz)

(Where qualifier.concat(brand.name()) its = "DaoA" for example)

This is the structure:

  • es.app.service
    • ServiceClass.java calls DaoFactory to get Impl.
  • es.app.dao
    • Dao.java
    • DaoBase.java implements Dao
    • DaoFactory.java
  • es.app.dao.impl
    • DaoAImpl.java extends DaoBase @Repository("DaoA")
    • DaoBImpl.java extends DaoBase @Repository("DaoB")
    • DaoCImpl.java extends DaoBase @Repository("DaoC")
    • DaoDImpl.java extends DaoBase @Repository("DaoD")

Then i have a test class on Test Packages

  • es.app.service

    ServiceClassTest.java

I put a little code for each class here:

DaoFactory.java

@Component
public class DaoFactory implements Serializable, ApplicationContextAware{

    private ApplicationContext  ctx;
    private static final long   serialVersionUID    = 1L;
    private static final Logger LOGGER  = LoggerFactory.getLogger(DaoFactory.class);

    public Dao getInstance(GroupBrand brand){
        switch(brand){
            case A:
            case B:
            case C:
            case D:
                return (Dao)getComponent("Dao",Dao.class, brand);
            default: break;
        }
        throw new IllegalArgumentException("Unsupported brand ".concat(brand.name()));
    }

    private Object getComponent(String qualifier, Class<?> clazz, GroupBrand brand){
        Object instance = ctx.getBean(qualifier.concat(brand.name()), clazz);
        if(Utils.isNull(instance)){
            throw new IllegalArgumentException("Unkown business bean with Qualifier:  ".concat(qualifier.concat(brand.name())).concat("type: ").concat(clazz.getName()));
        }
        LOGGER.debug("DAO retrived: " + qualifier.concat(brand.name()) +" class: " + clazz.getName());
        return instance;
    }


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.ctx = applicationContext;
    }


}

DaoBase.java

public abstract class DaoBase implements Dao {


    protected abstract EntityManager getEntityManager();
    private static final String EMPTY = "";
    private static final Logger     LOGGER  = LoggerFactory.getLogger(DaoBase.class);

    @Override
    public Boolean findAvailability(GroupBrand marca, String code) {
        EntityManager em = getEntityManager();
        Query query = em.createNamedQuery("Conn.isAvailability");
        query.setParameter(1, code);
        query.setParameter(2, marca.toCharCode());
        try{
            String value = (String)query.getSingleResult();
                        if(value.equalsIgnoreCase("S")){
                            return true;
                        }else{
                            return false;
                        }
        }catch(Exception ex){
            return Boolean.FALSE;
        }
    }

}

DaoAImpl.java

@Repository("DaoA")
public class DaoAImpl extends DaoBase {

    @PersistenceContext(unitName = "emA")
    private EntityManager em;

    @Override
    @Transactional("A")
    public Boolean findAvailability(GroupBrand marca, String code) {
        return super.findAvailability(marca, code);
    }
}

ServiceClass.java

    @Override
    public boolean isAvailable(GroupBrand brand, String code){
        Boolean available = getDMSQisAvailability(brand, code);
        return available;
    }

    protected Boolean isAvailability(GroupBrand marca, String kvps){
        boolean value = daoFactory.getInstance(marca).findDMSQisAvailability(marca, code);
        return value;
    }

ServiceClassTest.java

    @InjectMocks
        @Autowired
        @Qualifier("serviceClass")
        private ServiceClass srv;

    @Autowired
    @Qualifier("DaoFactory")
    protected DaoFactory daoFactory;

    @Mock
    protected Dao dao;

    @Override
    public void mockBehaivors() throws ResourceException, ResourceNotFoundException, ApiException {
        MockitoAnnotations.initMocks(this);

        dao = daoFactory.getInstance(marca);

        when(dao.findAvailability(any(GroupBrand.class), any(String.class))).thenReturn(Boolean.TRUE);

    }

    @Test
        public void isAvailableTest() throws ResourceException, Exception{
            Boolean available = srv.isAvailable(GroupBrand.A, "CODE");
        } 

I need to coverage ServiceClass.java class but i can't mock Dao calls from this Test class always do real call and don't return what i defined on "when", other tests works but are not using dao access.

Anyone can help me?

(Apologies for my poor english)..

Regards,


Answer:

At least i found a solution of my problem,

I haved to mock DaoFactory when calls getInstance() i return a mock of Dao class.

Class test it like this:

@InjectMocks
@Autowired
@Qualifier("serviceClass")
private ServiceClass srv;

@Mock
@Autowired
@Qualifier("DaoA")
protected Dao dao;

@Mock
@Autowired
@Qualifier("DaoFactory")
protected DaoFactory daoFactory;

@Override
public void mockBehaivors() throws ResourceException, ResourceNotFoundException, ApiException {
    MockitoAnnotations.initMocks(this);

    when(daoFactory.getInstance(GroupBrand.A)).thenReturn(dao);

    when(dao.findAvailability(any(GroupBrand.class), any(String.class))).thenReturn(Boolean.TRUE);

}

@Test
    public void isAvailableTest() throws ResourceException, Exception{
        Boolean available = srv.isAvailable(GroupBrand.A, "CODE");
    } 

And it's works!!!!

Question:

I'm trying to write some tests for my DAO's. I have followed some tutorials/answers here, but most of them don't apply to my DAO's.

Example code: trying to get the elections from the database based on the given selector (< or >).

public class AdminDaoImpl extends DaoImpl implements AdminDao {

    private final Logger LOGGER = Logger.getLogger(getClass().getName());

    @Override
    public ElectionListResponse getElections(char selector) {
        ElectionListResponse electionListResponse = new ElectionListResponse();

        String query = NamedQueries.GET_ELECTIONS_BEGIN + selector + NamedQueries.GET_ELECTIONS_END;

        try {
            con = sqlConnection.getConnection();
            stmt = con.prepareStatement(query);
            rs = stmt.executeQuery();

            DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");

            while (rs.next()) {
                Election election = new Election();
                election.setElectionID(rs.getInt("id"));
                election.setElectionName(rs.getString("name"));
                election.setStartDate(df.format(rs.getDate("startDate")));
                election.setEndDate(df.format(rs.getDate("endDate")));
                electionListResponse.addElection(election);
            }
            return electionListResponse;
        } catch (SQLException e) {
            LOGGER.log(Level.SEVERE, "Cant get elections. ", e);
        } finally {
            closeConnection();
        }
        return null;
    }

This is the DAO that the code above extends:

public abstract class DaoImpl implements Dao {

    private final Logger LOGGER = Logger.getLogger(getClass().getName());

    @Inject
    public SQLConnection sqlConnection;

    public Connection con;
    public PreparedStatement stmt;
    public ResultSet rs;

    public void closeConnection() {
        try {
            if (con != null) con.close();
            if (stmt != null) stmt.close();
            if (rs != null) con.close();
        } catch (SQLException e) {
            LOGGER.log(Level.SEVERE, "Can't close connection with database. ", e);
        }
    }
}

I have tried to apply some code that I found online and this is what I currently have:

@RunWith(MockitoJUnitRunner.class)
public class AdminDaoImplTest {

    @Mock
    DataSource mockDataSource;
    @Mock
    Connection mockConn;
    @Mock
    PreparedStatement mockPreparedStmnt;
    @Mock
    ResultSet mockResultSet;

    @BeforeClass
    public static void setUpClass() throws Exception {
    }

    @AfterClass
    public static void tearDownClass() {
    }

    @Before
    public void setUp() throws SQLException {
        when(mockDataSource.getConnection()).thenReturn(mockConn);
        when(mockDataSource.getConnection(anyString(), anyString())).thenReturn(mockConn);
        doNothing().when(mockConn).commit();
        when(mockConn.prepareStatement(anyString(), anyInt())).thenReturn(mockPreparedStmnt);
        doNothing().when(mockPreparedStmnt).setString(anyInt(), anyString());
        when(mockPreparedStmnt.executeQuery()).thenReturn(mockResultSet);
        when(mockResultSet.next()).thenReturn(Boolean.TRUE, Boolean.FALSE);
    }

    @After
    public void tearDown() {
    }

    @Test
    public void testCreateWithNoExceptions() throws SQLException {

        ElectionListResponse electionListResponse = new ElectionListResponse();

        AdminDaoImpl instance = new AdminDaoImpl();
        instance.getElections('>' );

        //verify and assert
        verify(mockConn, times(1)).prepareStatement(anyString(), anyInt());
        verify(mockPreparedStmnt, times(1)).execute();
        verify(mockConn, times(1)).commit();
        verify(mockResultSet, times(2)).next();
        verify(mockResultSet, times(1)).getInt("id");
        verify(mockResultSet, times(1)).getString("name");
        verify(mockResultSet, times(1)).getDate("startDate");
        verify(mockResultSet, times(1)).getDate("endDate");
    }


}

How should I test it ? Would you please produce some code samples? Thanks in advance!

NullPointer:

java.lang.NullPointerException
    at org.han.ica.oose.sneeuwklokje.database.admin.AdminDaoImpl.getElections(AdminDaoImpl.java:28)
    at org.han.ica.oose.sneeuwklokje.database.admin.AdminDaoImplTest.testGetElectionsNoExceptions(AdminDaoImplTest.java:77)
    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:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    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:137)
    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 should add to the test the following field:

@InjectMocks
private AdminDaoImpl

this will inject the mocks in your class, allowing you to test.

The NullPointerException you get can be fixed in this way (in test class):

@Mock
private SQLConnection mockSqlConnection;

in setup method add this:

when(mockSqlConnection.getConnection()).thenReturn(mockConn);