-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
AdrianBalunan
committed
Apr 24, 2026
1 parent
533e896
commit ce7e698
Showing
1 changed file
with
336 additions
and
1 deletion.
There are no files selected for viewing
337 changes: 336 additions & 1 deletion
337
...helpapplication/src/test/java/ntnu/systemutvikling/team6/database/DAO/CharityDAOTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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())); | ||
| } | ||
| } |