简体   繁体   中英

Mocked dao returns false when saving an object

I am new to test driven development. I am trying to test if an object has been successfully saved into my db. My code so far:

@ExtendWith(MockitoExtension.class)
public class ParkingDataBaseIT {
    @Mock
    private TicketDAO mockTicketDAO;
    
    @Mock
    public static DataBaseTestConfig mockDataBaseTestConfig = new DataBaseTestConfig();
    
    @Mock
    private static Connection mockConnection;

    @BeforeEach
    public void setup() throws SQLException, ClassNotFoundException {
        // Connection attempt.
        when(mockDataBaseTestConfig.getConnection()).thenReturn(mockConnection);
    }

    @AfterAll
    public static void tearDown() {
        // ...
    }

    @DisplayName("Tests if saving a ticket is successful.")
    @Test
    public void testParkingACarAlpha() throws SQLException, ClassNotFoundException {
        // Given.
        Date inTime = new Date();
        Ticket ticket = new Ticket();
        
        ticket.setVehicleRegNumber("ABCDEF");
        ticket.setPrice(0);
        ticket.setInTime(inTime);
        ticket.setOutTime(null);
        
        // When.
        // MockDao always returning false when saving.
        final boolean saved = mockTicketDAO.saveTicket(ticket, mockDataBaseTestConfig.getConnection());
        
        // Then.
        assertEquals(true, saved);
        assertThat(saved).isEqualTo(true);
    }
}

This is the method that makes the connection to MySQL:

public Connection getConnection() throws ClassNotFoundException, SQLException {
    Class.forName("com.mysql.cj.jdbc.Driver");
    return DriverManager.getConnection("jdbc:mysql://localhost:3306/testing", "root", "");
}

And finally this is how I save my ticket:

public boolean saveTicket(Ticket ticket, Connection con) {
    try {
        PreparedStatement ps = con.prepareStatement("insert into ticket(vehicleRegNumber, price, inTime, outTime) values(?, ?, ?, ?, ?)");
        
        ps.setInt(1, ticket.getParkingSpot().getId());
        ps.setString(2, ticket.getVehicleRegNumber());
        ps.setDouble(3, ticket.getPrice());
        ps.setTimestamp(4, new Timestamp(ticket.getInTime().getTime()));
        ps.setTimestamp(5, (ticket.getOutTime() == null) ? null: (new Timestamp(ticket.getOutTime().getTime())));
        
        return ps.execute();
    } catch (Exception e) {
        logger.error("Cannot fetch available slot.", e);
    } finally {
        dataBaseConfig.closeConnection(con);
    }
    
    return false;
}

The request using MySQL works, but while saving the object, I get a false from ps.execute(); instead of true, but I am certainly doing something wrong.

I noticed that ps is null in saveTicket(Ticket ticket, Connection con) (Cannot invoke "java.sql.PreparedStatement.setInt(int, int)" because "ps" is null), but con has mockConnection when I sysout the value.

Since mockDataBaseTestConfig.getConnection() always returned null, it obviously could not work.

After reviewing, I ended making it working by only mocking the dao (careful the test has been renamed to testSavingTicket_shouldReturnTrue).

private Ticket t;

@Test
public void testSavingTicket_shouldReturnTrue() throws SQLException, ClassNotFoundException {
    // Given.
    TicketDAO mockTicketDao = mock(TicketDAO.class);
    
    t = new Ticket();
    
    t.setVehicleRegNumber("ABCDEF");
    t.setPrice(0);
    t.setInTime(new Date());
    t.setOutTime(null);
    
    when(mockTicketDao.saveTicket(t)).thenReturn(true);
    
    // When.
    final boolean saved = mockTicketDao.saveTicket(t);
    
    // Then.
    assertEquals(true, saved);
    assertThat(saved).isEqualTo(true);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM