Skip to content

Commit

Permalink
Feat: Implemnetet CharityDAOTest
Browse files Browse the repository at this point in the history
  • Loading branch information
AdrianBalunan committed Apr 24, 2026
1 parent 533e896 commit ce7e698
Showing 1 changed file with 336 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -1,4 +1,339 @@
package ntnu.systemutvikling.team6.database.DAO;

import ntnu.systemutvikling.team6.database.DatabaseConnection;
import ntnu.systemutvikling.team6.models.Charity;
import ntnu.systemutvikling.team6.models.Feedback;
import ntnu.systemutvikling.team6.models.registry.CharityRegistry;
import ntnu.systemutvikling.team6.models.user.Language;
import ntnu.systemutvikling.team6.models.user.Role;
import org.junit.jupiter.api.*;
import java.sql.*;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.UUID;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;

public class CharityDAOTest {
}

// --- Mocks ---
private DatabaseConnection mockDbConnection;
private Connection mockConn;
private Statement mockRawStmt; // getCharitiesFromDB() uses createStatement()
private PreparedStatement mockStmt; // getFeedbackForCharityUUID() uses prepareStatement()
private ResultSet mockRs;

private CharityDAO charityDAO;

@BeforeEach
void setUp() throws SQLException {
mockDbConnection = mock(DatabaseConnection.class);
mockConn = mock(Connection.class);
mockRawStmt = mock(Statement.class);
mockStmt = mock(PreparedStatement.class);
mockRs = mock(ResultSet.class);

when(mockDbConnection.getMySqlConnection()).thenReturn(mockConn);
when(mockConn.createStatement()).thenReturn(mockRawStmt);
when(mockConn.prepareStatement(anyString())).thenReturn(mockStmt);

charityDAO = new CharityDAO(mockDbConnection);
}

// ----------------------------------------------------------------
// Helpers
// ----------------------------------------------------------------

/** Stubs the full set of charity columns for a single row. */
private void stubCharityRow(String charityId) throws SQLException {
when(mockRs.getString("UUID_charities")).thenReturn(charityId);
when(mockRs.getString("org_number")).thenReturn("123456789");
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 people");
when(mockRs.getString("logoURL")).thenReturn(null);
when(mockRs.getString("key_values")).thenReturn(null);
when(mockRs.getBytes("logoBLOB")).thenReturn(null);
when(mockRs.getString("category")).thenReturn(null);
when(mockRs.getString("UUID_feedback")).thenReturn(null); // no feedback by default
}

/** Stubs a feedback + user block on top of an already-stubbed charity row. */
private void stubFeedbackRow(String feedbackId, String userId) throws SQLException {
when(mockRs.getString("UUID_feedback")).thenReturn(feedbackId);
when(mockRs.getString("feedback_comment")).thenReturn("Great charity!");
when(mockRs.getString("feedback_date")).thenReturn(LocalDate.now().toString());
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());
}

// ----------------------------------------------------------------
// getCharitiesFromDB() — uses createStatement()
// ----------------------------------------------------------------

@Test
void getCharitiesFromDB_returnsRegistryWithOneCharity() throws SQLException {
when(mockRawStmt.executeQuery(anyString())).thenReturn(mockRs);
when(mockRs.next()).thenReturn(true, false);

String charityId = UUID.randomUUID().toString();
stubCharityRow(charityId);

CharityRegistry registry = charityDAO.getCharitiesFromDB();

assertNotNull(registry);
assertEquals(1, registry.getAllCharities().size());
assertEquals(charityId, registry.getAllCharities().getFirst().getUUID().toString());
assertEquals("HelpOrg", registry.getAllCharities().getFirst().getName());
}

@Test
void getCharitiesFromDB_returnsEmptyRegistryWhenNoRows() throws SQLException {
when(mockRawStmt.executeQuery(anyString())).thenReturn(mockRs);
when(mockRs.next()).thenReturn(false);

CharityRegistry registry = charityDAO.getCharitiesFromDB();

assertNotNull(registry);
assertTrue(registry.getAllCharities().isEmpty());
}

@Test
void getCharitiesFromDB_doesNotDuplicateCharityAcrossMultipleRows() throws SQLException {
// Same charity appearing in two rows (e.g. two categories) → only one Charity object
when(mockRawStmt.executeQuery(anyString())).thenReturn(mockRs);
when(mockRs.next()).thenReturn(true, true, false);

String charityId = UUID.randomUUID().toString();
when(mockRs.getString("UUID_charities")).thenReturn(charityId);
when(mockRs.getString("org_number")).thenReturn("111");
when(mockRs.getString("charity_name")).thenReturn("EduOrg");
when(mockRs.getString("charity_link")).thenReturn("eduorg.com");
when(mockRs.getString("status")).thenReturn("active");
when(mockRs.getBoolean("pre_approved")).thenReturn(false);
when(mockRs.getString("description")).thenReturn("Education");
when(mockRs.getString("logoURL")).thenReturn(null);
when(mockRs.getString("key_values")).thenReturn(null);
when(mockRs.getBytes("logoBLOB")).thenReturn(null);
when(mockRs.getString("category")).thenReturn("Education", "Youth");
when(mockRs.getString("UUID_feedback")).thenReturn(null);

CharityRegistry registry = charityDAO.getCharitiesFromDB();

assertEquals(1, registry.getAllCharities().size());
assertEquals(2, registry.getAllCharities().getFirst().getCategory().size());
assertTrue(registry.getAllCharities().getFirst().getCategory().contains("Education"));
assertTrue(registry.getAllCharities().getFirst().getCategory().contains("Youth"));
}

@Test
void getCharitiesFromDB_returnsMultipleDistinctCharities() throws SQLException {
when(mockRawStmt.executeQuery(anyString())).thenReturn(mockRs);
when(mockRs.next()).thenReturn(true, true, false);

String charityId1 = UUID.randomUUID().toString();
String charityId2 = UUID.randomUUID().toString();

when(mockRs.getString("UUID_charities")).thenReturn(charityId1, charityId2);
when(mockRs.getString("org_number")).thenReturn("111", "222");
when(mockRs.getString("charity_name")).thenReturn("OrgA", "OrgB");
when(mockRs.getString("charity_link")).thenReturn("orga.com", "orgb.com");
when(mockRs.getString("status")).thenReturn("active");
when(mockRs.getBoolean("pre_approved")).thenReturn(true);
when(mockRs.getString("description")).thenReturn("Desc");
when(mockRs.getString("logoURL")).thenReturn(null);
when(mockRs.getString("key_values")).thenReturn(null);
when(mockRs.getBytes("logoBLOB")).thenReturn(null);
when(mockRs.getString("category")).thenReturn(null);
when(mockRs.getString("UUID_feedback")).thenReturn(null);

CharityRegistry registry = charityDAO.getCharitiesFromDB();

assertEquals(2, registry.getAllCharities().size());
}

@Test
void getCharitiesFromDB_appendsFeedbackToCharity() throws SQLException {
when(mockRawStmt.executeQuery(anyString())).thenReturn(mockRs);
when(mockRs.next()).thenReturn(true, false);

String charityId = UUID.randomUUID().toString();
String feedbackId = UUID.randomUUID().toString();
String userId = UUID.randomUUID().toString();

stubCharityRow(charityId);
stubFeedbackRow(feedbackId, userId);

CharityRegistry registry = charityDAO.getCharitiesFromDB();

Charity charity = registry.getAllCharities().getFirst();
assertEquals(1, charity.getFeedbacks().size());
assertEquals(feedbackId, charity.getFeedbacks().getFirst().getFeedbackId().toString());
assertEquals("Great charity!", charity.getFeedbacks().getFirst().getComment());
assertEquals(userId, charity.getFeedbacks().getFirst().getUser().getId().toString());
}

@Test
void getCharitiesFromDB_doesNotDuplicateFeedbackAcrossRows() throws SQLException {
// Same feedbackId appearing in two rows (e.g. two categories) → only one Feedback added
when(mockRawStmt.executeQuery(anyString())).thenReturn(mockRs);
when(mockRs.next()).thenReturn(true, true, false);

String charityId = UUID.randomUUID().toString();
String feedbackId = UUID.randomUUID().toString();
String userId = UUID.randomUUID().toString();

when(mockRs.getString("UUID_charities")).thenReturn(charityId);
when(mockRs.getString("org_number")).thenReturn("111");
when(mockRs.getString("charity_name")).thenReturn("Org");
when(mockRs.getString("charity_link")).thenReturn("org.com");
when(mockRs.getString("status")).thenReturn("active");
when(mockRs.getBoolean("pre_approved")).thenReturn(false);
when(mockRs.getString("description")).thenReturn("desc");
when(mockRs.getString("logoURL")).thenReturn(null);
when(mockRs.getString("key_values")).thenReturn(null);
when(mockRs.getBytes("logoBLOB")).thenReturn(null);
when(mockRs.getString("category")).thenReturn("Health", "Health");
stubFeedbackRow(feedbackId, userId); // same feedbackId both rows

CharityRegistry registry = charityDAO.getCharitiesFromDB();

assertEquals(1, registry.getAllCharities().getFirst().getFeedbacks().size());
}

@Test
void getCharitiesFromDB_clearsSeenFeedbackIdsWhenNewCharityStarts() throws SQLException {
// feedbackId seen on charity1 must NOT be deduplicated against charity2
when(mockRawStmt.executeQuery(anyString())).thenReturn(mockRs);
when(mockRs.next()).thenReturn(true, true, false);

String charityId1 = UUID.randomUUID().toString();
String charityId2 = UUID.randomUUID().toString();
String feedbackId = UUID.randomUUID().toString(); // same UUID reused on both charities
String userId = UUID.randomUUID().toString();

when(mockRs.getString("UUID_charities")).thenReturn(charityId1, charityId2);
when(mockRs.getString("org_number")).thenReturn("111", "222");
when(mockRs.getString("charity_name")).thenReturn("OrgA", "OrgB");
when(mockRs.getString("charity_link")).thenReturn("a.com", "b.com");
when(mockRs.getString("status")).thenReturn("active");
when(mockRs.getBoolean("pre_approved")).thenReturn(true);
when(mockRs.getString("description")).thenReturn("desc");
when(mockRs.getString("logoURL")).thenReturn(null);
when(mockRs.getString("key_values")).thenReturn(null);
when(mockRs.getBytes("logoBLOB")).thenReturn(null);
when(mockRs.getString("category")).thenReturn(null);
when(mockRs.getString("UUID_feedback")).thenReturn(feedbackId);
when(mockRs.getString("feedback_comment")).thenReturn("Good");
when(mockRs.getString("feedback_date")).thenReturn(LocalDate.now().toString());
when(mockRs.getString("UUID_User")).thenReturn(userId);
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());

CharityRegistry registry = charityDAO.getCharitiesFromDB();

// Each charity should have its own feedback entry
assertEquals(1, registry.getAllCharities().get(0).getFeedbacks().size());
assertEquals(1, registry.getAllCharities().get(1).getFeedbacks().size());
}

@Test
void getCharitiesFromDB_throwsRuntimeExceptionOnSQLException() throws SQLException {
when(mockConn.createStatement()).thenThrow(new SQLException("DB down"));

assertThrows(RuntimeException.class, () -> charityDAO.getCharitiesFromDB());
}

// ----------------------------------------------------------------
// getFeedbackForCharityUUID() — uses prepareStatement()
// ----------------------------------------------------------------

@Test
void getFeedbackForCharityUUID_returnsFeedbackList() throws SQLException {
when(mockStmt.executeQuery()).thenReturn(mockRs);
when(mockRs.next()).thenReturn(true, false);

String feedbackId = UUID.randomUUID().toString();
String userId = UUID.randomUUID().toString();

when(mockRs.getString("UUID_feedback")).thenReturn(feedbackId);
when(mockRs.getString("feedback_comment")).thenReturn("Very helpful");
when(mockRs.getString("feedback_date")).thenReturn(LocalDate.now().toString());
when(mockRs.getBoolean("isAnonymous")).thenReturn(false);
when(mockRs.getString("UUID_User")).thenReturn(userId);
when(mockRs.getString("user_name")).thenReturn("Carol");
when(mockRs.getString("user_email")).thenReturn("carol@example.com");
when(mockRs.getString("user_password")).thenReturn("pw");
when(mockRs.getString("role")).thenReturn(Role.NORMAL_USER.toString());
when(mockRs.getString("language")).thenReturn(Language.ENGLISH.toString());
when(mockRs.getBoolean("lightmode")).thenReturn(false);

ArrayList<Feedback> result = charityDAO.getFeedbackforCharityUUID(UUID.randomUUID().toString());

assertNotNull(result);
assertEquals(1, result.size());
assertEquals(feedbackId, result.getFirst().getFeedbackId().toString());
assertEquals("Very helpful", result.getFirst().getComment());
assertEquals(userId, result.getFirst().getUser().getId().toString());
}

@Test
void getFeedbackForCharityUUID_returnsEmptyListWhenNoFeedback() throws SQLException {
when(mockStmt.executeQuery()).thenReturn(mockRs);
when(mockRs.next()).thenReturn(false);

ArrayList<Feedback> result = charityDAO.getFeedbackforCharityUUID(UUID.randomUUID().toString());

assertNotNull(result);
assertTrue(result.isEmpty());
}

@Test
void getFeedbackForCharityUUID_returnsMultipleEntries() throws SQLException {
when(mockStmt.executeQuery()).thenReturn(mockRs);
when(mockRs.next()).thenReturn(true, true, false);

when(mockRs.getString("UUID_feedback")).thenReturn(
UUID.randomUUID().toString(), UUID.randomUUID().toString());
when(mockRs.getString("feedback_comment")).thenReturn("Good", "Excellent");
when(mockRs.getString("feedback_date")).thenReturn(LocalDate.now().toString());
when(mockRs.getBoolean("isAnonymous")).thenReturn(false);
when(mockRs.getString("UUID_User")).thenReturn(UUID.randomUUID().toString());
when(mockRs.getString("user_name")).thenReturn("User");
when(mockRs.getString("user_email")).thenReturn("u@example.com");
when(mockRs.getString("user_password")).thenReturn("pw");
when(mockRs.getString("role")).thenReturn(Role.NORMAL_USER.toString());
when(mockRs.getString("language")).thenReturn(Language.ENGLISH.toString());
when(mockRs.getBoolean("lightmode")).thenReturn(false);

ArrayList<Feedback> result = charityDAO.getFeedbackforCharityUUID(UUID.randomUUID().toString());

assertEquals(2, result.size());
}

@Test
void getFeedbackForCharityUUID_passesCorrectCharityIdToQuery() throws SQLException {
when(mockStmt.executeQuery()).thenReturn(mockRs);
when(mockRs.next()).thenReturn(false);

String charityId = UUID.randomUUID().toString();
charityDAO.getFeedbackforCharityUUID(charityId);

verify(mockStmt).setString(1, charityId);
}

@Test
void getFeedbackForCharityUUID_throwsRuntimeExceptionOnSQLException() throws SQLException {
when(mockStmt.executeQuery()).thenThrow(new SQLException("Query failed"));

assertThrows(RuntimeException.class,
() -> charityDAO.getFeedbackforCharityUUID(UUID.randomUUID().toString()));
}
}

0 comments on commit ce7e698

Please sign in to comment.