diff --git a/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/database/DAO/DonationDAOTest.java b/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/database/DAO/DonationDAOTest.java index 74b97af..f6f4ae7 100644 --- a/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/database/DAO/DonationDAOTest.java +++ b/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/database/DAO/DonationDAOTest.java @@ -1,78 +1,343 @@ package ntnu.systemutvikling.team6.database.DAO; -import static org.junit.jupiter.api.Assertions.*; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.time.LocalDate; -import java.util.UUID; import ntnu.systemutvikling.team6.database.DatabaseConnection; -import ntnu.systemutvikling.team6.database.DatabaseSetup; import ntnu.systemutvikling.team6.models.Charity; import ntnu.systemutvikling.team6.models.Donation; -import ntnu.systemutvikling.team6.models.user.Inbox; -import ntnu.systemutvikling.team6.models.user.Role; -import ntnu.systemutvikling.team6.models.user.Settings; -import ntnu.systemutvikling.team6.models.user.User; -import ntnu.systemutvikling.team6.service.APIToDatabaseService; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; +import ntnu.systemutvikling.team6.models.registry.DonationRegistry; +import ntnu.systemutvikling.team6.models.user.*; +import org.junit.jupiter.api.*; +import java.sql.*; +import java.time.LocalDate; +import java.util.UUID; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; -class DonationDAOTest { +public class DonationDAOTest { - private Charity charity; + // --- Mocks --- + private DatabaseConnection mockDbConnection; + private Connection mockConn; + private PreparedStatement mockStmt; + private Statement mockRawStmt; // getDonationFromDB() uses createStatement(), not prepareStatement() + private ResultSet mockRs; + + private DonationDAO donationDAO; @BeforeEach - void setUp() { - DatabaseConnection conn = new DatabaseConnection(); - DatabaseSetup manager = new DatabaseSetup(conn); - manager.createTables(); - - charity = - new Charity( - "123456", - "https://www.innsamlingskontrollen.no/organisasjoner/adra-norge-adventist-development-and-relief-agency-norway/", - "Test Charity", - true, - "approved"); + void setUp() throws SQLException { + mockDbConnection = mock(DatabaseConnection.class); + mockConn = mock(Connection.class); + mockStmt = mock(PreparedStatement.class); + mockRawStmt = mock(Statement.class); + mockRs = mock(ResultSet.class); + + when(mockDbConnection.getMySqlConnection()).thenReturn(mockConn); + when(mockConn.prepareStatement(anyString())).thenReturn(mockStmt); + when(mockConn.createStatement()).thenReturn(mockRawStmt); - APIToDatabaseService service = new APIToDatabaseService(conn); - service.addAPIDataToTable(java.util.List.of(charity)); + donationDAO = new DonationDAO(mockDbConnection); } - @Test - void addDonationShouldInsertDonationIntoDatabase() throws Exception { - double amount = 100.0; + // ---------------------------------------------------------------- + // Helpers + // ---------------------------------------------------------------- - DonationDAO donationDAO = new DonationDAO(new DatabaseConnection()); + private User buildTestUser(String userId) { + User user = new User( + userId, + "TestUser", + "test@example.com", + "hashedpassword", + Role.NORMAL_USER.toString() + ); + user.setSettings(new Settings(false, Language.ENGLISH, true)); + user.setInbox(new Inbox()); + return user; + } + private Charity buildTestCharity(String charityId) { + return new Charity( + charityId, + "123456789", + "HelpOrg", + "helporg.com", + "active", + true, + "We help people", + null, + null, + null + ); + } - User user = new User( - UUID.randomUUID().toString(), - "ad", - "aduser", - Role.NORMAL_USER, - new Settings(), - new Inbox()); - donationDAO.addDonation(new Donation( - amount, + private Donation buildTestDonation(String donationId, User user, Charity charity) { + return new Donation( + donationId, + 100.0, LocalDate.now(), charity, - user - )); + user, + false + ); + } - try (Connection conn = new DatabaseConnection().getMySqlConnection()) { - PreparedStatement stmt = - conn.prepareStatement("SELECT amount FROM Donations WHERE charity_id = ?"); + /** Stubs all ResultSet columns shared by getDonationFromDB, getDonationForUser, getDonationForCharity. */ + private void stubFullDonationRow(String donationId, String charityId, String userId) throws SQLException { + when(mockRs.getString("UUID_Donations")).thenReturn(donationId); + when(mockRs.getDouble("amount")).thenReturn(250.0); + when(mockRs.getBoolean("isAnonymous")).thenReturn(false); + when(mockRs.getDate("date")).thenReturn(Date.valueOf(LocalDate.now())); - stmt.setString(1, charity.getUUID().toString()); + when(mockRs.getString("UUID_charities")).thenReturn(charityId); + when(mockRs.getString("org_number")).thenReturn("9999"); + when(mockRs.getString("charity_name")).thenReturn("HelpOrg"); + when(mockRs.getString("charity_link")).thenReturn("helporg.com"); + when(mockRs.getString("status")).thenReturn("active"); + when(mockRs.getBoolean("pre_approved")).thenReturn(true); + when(mockRs.getString("description")).thenReturn("We help"); + when(mockRs.getString("logoURL")).thenReturn(null); + when(mockRs.getString("key_values")).thenReturn(null); + when(mockRs.getBytes("logoBLOB")).thenReturn(null); - ResultSet rs = stmt.executeQuery(); + when(mockRs.getString("UUID_User")).thenReturn(userId); + when(mockRs.getString("user_name")).thenReturn("Alice"); + when(mockRs.getString("user_email")).thenReturn("alice@example.com"); + when(mockRs.getString("user_password")).thenReturn("hashedpw"); + when(mockRs.getString("role")).thenReturn(Role.NORMAL_USER.toString()); + } - assertTrue(rs.next(), "Donation should exist in database"); + // ---------------------------------------------------------------- + // getDonationFromDB() — uses createStatement(), not prepareStatement() + // ---------------------------------------------------------------- - assertEquals(amount, rs.getDouble("amount")); - } + @Test + void getDonationFromDB_returnsRegistryWithDonations() throws SQLException { + when(mockRawStmt.executeQuery(anyString())).thenReturn(mockRs); + when(mockRs.next()).thenReturn(true, false); + + String donationId = UUID.randomUUID().toString(); + String charityId = UUID.randomUUID().toString(); + String userId = UUID.randomUUID().toString(); + stubFullDonationRow(donationId, charityId, userId); + + DonationRegistry registry = donationDAO.getDonationFromDB(); + + assertNotNull(registry); + assertEquals(1, registry.getAllDonations().size()); + assertEquals(donationId, registry.getAllDonations().getFirst().getDonationID().toString()); + assertEquals(250.0, registry.getAllDonations().getFirst().getAmount()); + assertEquals(charityId, registry.getAllDonations().getFirst().getCharity().getUUID().toString()); + assertEquals(userId, registry.getAllDonations().getFirst().getDonor().getId().toString()); + } + + @Test + void getDonationFromDB_returnsEmptyRegistryWhenNoDonations() throws SQLException { + when(mockRawStmt.executeQuery(anyString())).thenReturn(mockRs); + when(mockRs.next()).thenReturn(false); + + DonationRegistry registry = donationDAO.getDonationFromDB(); + + assertNotNull(registry); + assertTrue(registry.getAllDonations().isEmpty()); + } + + @Test + void getDonationFromDB_returnsMultipleDonations() throws SQLException { + when(mockRawStmt.executeQuery(anyString())).thenReturn(mockRs); + when(mockRs.next()).thenReturn(true, true, false); + + when(mockRs.getString("UUID_Donations")).thenReturn( + UUID.randomUUID().toString(), UUID.randomUUID().toString()); + when(mockRs.getDouble("amount")).thenReturn(100.0, 200.0); + when(mockRs.getBoolean("isAnonymous")).thenReturn(false); + when(mockRs.getDate("date")).thenReturn(Date.valueOf(LocalDate.now())); + when(mockRs.getString("UUID_charities")).thenReturn(UUID.randomUUID().toString()); + when(mockRs.getString("org_number")).thenReturn("1111"); + when(mockRs.getBoolean("pre_approved")).thenReturn(true); + when(mockRs.getString("status")).thenReturn("active"); + when(mockRs.getString("UUID_User")).thenReturn(UUID.randomUUID().toString()); + when(mockRs.getString("user_name")).thenReturn("Bob"); + when(mockRs.getString("user_email")).thenReturn("bob@example.com"); + when(mockRs.getString("user_password")).thenReturn("pw"); + when(mockRs.getString("role")).thenReturn(Role.NORMAL_USER.toString()); + + DonationRegistry registry = donationDAO.getDonationFromDB(); + + assertEquals(2, registry.getAllDonations().size()); + } + + @Test + void getDonationFromDB_throwsRuntimeExceptionOnSQLException() throws SQLException { + when(mockConn.createStatement()).thenThrow(new SQLException("DB down")); + + assertThrows(RuntimeException.class, () -> donationDAO.getDonationFromDB()); + } + + // ---------------------------------------------------------------- + // getDonationForUser() + // ---------------------------------------------------------------- + + @Test + void getDonationForUser_returnsRegistryWithDonations() throws SQLException { + when(mockStmt.executeQuery()).thenReturn(mockRs); + when(mockRs.next()).thenReturn(true, false); + + String donationId = UUID.randomUUID().toString(); + String charityId = UUID.randomUUID().toString(); + String userId = UUID.randomUUID().toString(); + stubFullDonationRow(donationId, charityId, userId); + + DonationRegistry registry = donationDAO.getDonationForUser(userId); + + assertNotNull(registry); + assertEquals(1, registry.getAllDonations().size()); + assertEquals(donationId, registry.getAllDonations().getFirst().getDonationID().toString()); + assertEquals(userId, registry.getAllDonations().getFirst().getDonor().getId().toString()); + } + + @Test + void getDonationForUser_returnsEmptyRegistryWhenNoDonations() throws SQLException { + when(mockStmt.executeQuery()).thenReturn(mockRs); + when(mockRs.next()).thenReturn(false); + + DonationRegistry registry = donationDAO.getDonationForUser(UUID.randomUUID().toString()); + + assertNotNull(registry); + assertTrue(registry.getAllDonations().isEmpty()); + } + + @Test + void getDonationForUser_passesCorrectUserIdToQuery() throws SQLException { + when(mockStmt.executeQuery()).thenReturn(mockRs); + when(mockRs.next()).thenReturn(false); + + String userId = UUID.randomUUID().toString(); + donationDAO.getDonationForUser(userId); + + verify(mockStmt).setString(1, userId); + } + + @Test + void getDonationForUser_throwsRuntimeExceptionOnSQLException() throws SQLException { + when(mockConn.prepareStatement(anyString())).thenThrow(new SQLException("Query failed")); + + assertThrows(RuntimeException.class, + () -> donationDAO.getDonationForUser(UUID.randomUUID().toString())); + } + + // ---------------------------------------------------------------- + // getDonationForCharity() + // ---------------------------------------------------------------- + + @Test + void getDonationForCharity_returnsRegistryWithDonations() throws SQLException { + when(mockStmt.executeQuery()).thenReturn(mockRs); + when(mockRs.next()).thenReturn(true, false); + + String donationId = UUID.randomUUID().toString(); + String charityId = UUID.randomUUID().toString(); + String userId = UUID.randomUUID().toString(); + stubFullDonationRow(donationId, charityId, userId); + + DonationRegistry registry = donationDAO.getDonationForCharity(charityId); + + assertNotNull(registry); + assertEquals(1, registry.getAllDonations().size()); + assertEquals(donationId, registry.getAllDonations().getFirst().getDonationID().toString()); + assertEquals(charityId, registry.getAllDonations().getFirst().getCharity().getUUID().toString()); + } + + @Test + void getDonationForCharity_returnsEmptyRegistryWhenNoDonations() throws SQLException { + when(mockStmt.executeQuery()).thenReturn(mockRs); + when(mockRs.next()).thenReturn(false); + + DonationRegistry registry = donationDAO.getDonationForCharity(UUID.randomUUID().toString()); + + assertNotNull(registry); + assertTrue(registry.getAllDonations().isEmpty()); + } + + @Test + void getDonationForCharity_passesCorrectCharityIdToQuery() throws SQLException { + when(mockStmt.executeQuery()).thenReturn(mockRs); + when(mockRs.next()).thenReturn(false); + + String charityId = UUID.randomUUID().toString(); + donationDAO.getDonationForCharity(charityId); + + verify(mockStmt).setString(1, charityId); + } + + @Test + void getDonationForCharity_throwsRuntimeExceptionOnSQLException() throws SQLException { + when(mockConn.prepareStatement(anyString())).thenThrow(new SQLException("Query failed")); + + assertThrows(RuntimeException.class, + () -> donationDAO.getDonationForCharity(UUID.randomUUID().toString())); + } + + // ---------------------------------------------------------------- + // addDonation() + // ---------------------------------------------------------------- + + @Test + void addDonation_executesSuccessfully() throws SQLException { + String donationId = UUID.randomUUID().toString(); + String charityId = UUID.randomUUID().toString(); + String userId = UUID.randomUUID().toString(); + User user = buildTestUser(userId); + Donation donation = buildTestDonation(donationId, user, buildTestCharity(charityId)); + + donationDAO.addDonation(donation); + + verify(mockStmt).executeUpdate(); + verify(mockConn).setAutoCommit(false); + verify(mockConn).commit(); + } + + @Test + void addDonation_setsCorrectParameterOrder() throws SQLException { + String donationId = UUID.randomUUID().toString(); + String charityId = UUID.randomUUID().toString(); + String userId = UUID.randomUUID().toString(); + User user = buildTestUser(userId); + Donation donation = buildTestDonation(donationId, user, buildTestCharity(charityId)); + + donationDAO.addDonation(donation); + + verify(mockStmt).setString(1, donationId); // UUID_Donations + verify(mockStmt).setDouble(2, donation.getAmount()); // amount + verify(mockStmt).setBoolean(3, user.getSettings().isAnonymous()); // isAnonymous + verify(mockStmt).setDate(4, Date.valueOf(donation.getDate())); // date + verify(mockStmt).setString(5, charityId); // charity_id + verify(mockStmt).setString(6, userId); // user_id + } + + @Test + void addDonation_setsAnonymousTrueWhenUserIsAnonymous() throws SQLException { + String userId = UUID.randomUUID().toString(); + User anonymousUser = buildTestUser(userId); + anonymousUser.setSettings(new Settings(true, Language.ENGLISH, false)); + + donationDAO.addDonation(buildTestDonation( + UUID.randomUUID().toString(), + anonymousUser, + buildTestCharity(UUID.randomUUID().toString()) + )); + + verify(mockStmt).setBoolean(3, true); + } + + @Test + void addDonation_throwsRuntimeExceptionOnSQLException() throws SQLException { + when(mockConn.prepareStatement(anyString())).thenThrow(new SQLException("Insert failed")); + + assertThrows(RuntimeException.class, + () -> donationDAO.addDonation(buildTestDonation( + UUID.randomUUID().toString(), + buildTestUser(UUID.randomUUID().toString()), + buildTestCharity(UUID.randomUUID().toString()) + ))); } -} +} \ No newline at end of file