Skip to content

Commit 83aa140

Browse files
authored
Merge pull request #38 from Stcwal/test/exceptions
Test/exceptions
2 parents 3efc09f + e94ded2 commit 83aa140

7 files changed

Lines changed: 274 additions & 2 deletions

File tree

backend/src/main/java/backend/fullstack/exceptions/AccessDeniedException.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package backend.fullstack.exceptions;
22

3-
import backend.fullstack.exceptions.AppException;
4-
53
/**
64
* Exception thrown when a user attempts to access a resource or perform an action for which they do not have the necessary permissions.
75
*

backend/src/main/java/backend/fullstack/exceptions/InvalidPasswordException.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
import org.springframework.http.HttpStatus;
44

5+
/**
6+
* Exception thrown when provided authentication credentials contain an invalid password.
7+
*
8+
* @version 1.0
9+
* @since 31.03.26
10+
*/
511
public class InvalidPasswordException extends AppException {
612

713
/**

backend/src/main/java/backend/fullstack/exceptions/InvalidThresholdException.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,17 @@
22

33
import org.springframework.http.HttpStatus;
44

5+
/**
6+
* Exception thrown when provided threshold values do not satisfy required ordering constraints.
7+
*
8+
* @version 1.0
9+
* @since 31.03.26
10+
*/
511
public class InvalidThresholdException extends AppException {
612

13+
/**
14+
* Constructs a new InvalidThresholdException with a standard validation message.
15+
*/
716
public InvalidThresholdException() {
817
super("Invalid thresholds: expected minThreshold < targetTemperature < maxThreshold", HttpStatus.BAD_REQUEST,
918
"INVALID_THRESHOLD");

backend/src/main/java/backend/fullstack/exceptions/OrganizationConflictException.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
import org.springframework.http.HttpStatus;
44

5+
/**
6+
* Exception thrown when an organization operation violates a uniqueness or business constraint.
7+
*
8+
* @version 1.0
9+
* @since 31.03.26
10+
*/
511
public class OrganizationConflictException extends AppException {
612

713
/**

backend/src/main/java/backend/fullstack/exceptions/UnitInactiveException.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,19 @@
22

33
import org.springframework.http.HttpStatus;
44

5+
/**
6+
* Exception thrown when an operation targets a temperature unit that exists but is inactive.
7+
*
8+
* @version 1.0
9+
* @since 31.03.26
10+
*/
511
public class UnitInactiveException extends AppException {
612

13+
/**
14+
* Constructs a new UnitInactiveException for the provided temperature unit identifier.
15+
*
16+
* @param unitId the inactive temperature unit identifier
17+
*/
718
public UnitInactiveException(Long unitId) {
819
super("Temperature unit is inactive: " + unitId, HttpStatus.CONFLICT, "UNIT_INACTIVE");
920
}

backend/src/main/java/backend/fullstack/exceptions/UnitNotFoundException.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,19 @@
22

33
import org.springframework.http.HttpStatus;
44

5+
/**
6+
* Exception thrown when a temperature unit cannot be found by identifier.
7+
*
8+
* @version 1.0
9+
* @since 31.03.26
10+
*/
511
public class UnitNotFoundException extends AppException {
612

13+
/**
14+
* Constructs a new UnitNotFoundException for the missing temperature unit identifier.
15+
*
16+
* @param unitId the missing temperature unit identifier
17+
*/
718
public UnitNotFoundException(Long unitId) {
819
super("Temperature unit not found with id: " + unitId, HttpStatus.NOT_FOUND, "UNIT_NOT_FOUND");
920
}
Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
package backend.fullstack.exceptions;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertNull;
5+
import static org.junit.jupiter.api.Assertions.assertSame;
6+
7+
import org.junit.jupiter.api.Test;
8+
import org.springframework.http.HttpStatus;
9+
10+
class ExceptionsTest {
11+
12+
@Test
13+
void appExceptionStoresStatusAndErrorCodeWithoutCause() {
14+
TestAppException exception = new TestAppException("boom", HttpStatus.BAD_REQUEST, "TEST_ERROR");
15+
16+
assertEquals("boom", exception.getMessage());
17+
assertEquals(HttpStatus.BAD_REQUEST, exception.getHttpStatus());
18+
assertEquals("TEST_ERROR", exception.getErrorCode());
19+
assertNull(exception.getCause());
20+
}
21+
22+
@Test
23+
void appExceptionStoresStatusAndErrorCodeWithCause() {
24+
RuntimeException cause = new RuntimeException("root");
25+
TestAppException exception = new TestAppException("boom", cause, HttpStatus.CONFLICT, "TEST_ERROR");
26+
27+
assertEquals("boom", exception.getMessage());
28+
assertEquals(HttpStatus.CONFLICT, exception.getHttpStatus());
29+
assertEquals("TEST_ERROR", exception.getErrorCode());
30+
assertSame(cause, exception.getCause());
31+
}
32+
33+
@Test
34+
void accessDeniedExceptionSingleArgumentConstructor() {
35+
AccessDeniedException exception = new AccessDeniedException("forbidden");
36+
37+
assertEquals("forbidden", exception.getMessage());
38+
assertEquals(HttpStatus.FORBIDDEN, exception.getHttpStatus());
39+
assertEquals("ACCESS_DENIED", exception.getErrorCode());
40+
assertNull(exception.getCause());
41+
}
42+
43+
@Test
44+
void accessDeniedExceptionMessageAndCauseConstructor() {
45+
RuntimeException cause = new RuntimeException("root");
46+
AccessDeniedException exception = new AccessDeniedException("forbidden", cause);
47+
48+
assertEquals("forbidden", exception.getMessage());
49+
assertEquals(HttpStatus.FORBIDDEN, exception.getHttpStatus());
50+
assertEquals("ACCESS_DENIED", exception.getErrorCode());
51+
assertSame(cause, exception.getCause());
52+
}
53+
54+
@Test
55+
void invalidPasswordExceptionSetsUnauthorizedMetadata() {
56+
InvalidPasswordException exception = new InvalidPasswordException("invalid credentials");
57+
58+
assertEquals("invalid credentials", exception.getMessage());
59+
assertEquals(HttpStatus.UNAUTHORIZED, exception.getHttpStatus());
60+
assertEquals("INVALID_PASSWORD", exception.getErrorCode());
61+
}
62+
63+
@Test
64+
void invalidThresholdExceptionUsesDefaultMessageAndMetadata() {
65+
InvalidThresholdException exception = new InvalidThresholdException();
66+
67+
assertEquals("Invalid thresholds: expected minThreshold < targetTemperature < maxThreshold", exception.getMessage());
68+
assertEquals(HttpStatus.BAD_REQUEST, exception.getHttpStatus());
69+
assertEquals("INVALID_THRESHOLD", exception.getErrorCode());
70+
}
71+
72+
@Test
73+
void locationExceptionSingleArgumentConstructor() {
74+
LocationException exception = new LocationException("location conflict");
75+
76+
assertEquals("location conflict", exception.getMessage());
77+
assertEquals(HttpStatus.CONFLICT, exception.getHttpStatus());
78+
assertEquals("LOCATION_ERROR", exception.getErrorCode());
79+
assertNull(exception.getCause());
80+
}
81+
82+
@Test
83+
void locationExceptionMessageAndCauseConstructor() {
84+
RuntimeException cause = new RuntimeException("root");
85+
LocationException exception = new LocationException("location conflict", cause);
86+
87+
assertEquals("location conflict", exception.getMessage());
88+
assertEquals(HttpStatus.CONFLICT, exception.getHttpStatus());
89+
assertEquals("LOCATION_ERROR", exception.getErrorCode());
90+
assertSame(cause, exception.getCause());
91+
}
92+
93+
@Test
94+
void organizationConflictExceptionSetsConflictMetadata() {
95+
OrganizationConflictException exception = new OrganizationConflictException("organization exists");
96+
97+
assertEquals("organization exists", exception.getMessage());
98+
assertEquals(HttpStatus.CONFLICT, exception.getHttpStatus());
99+
assertEquals("ORGANIZATION_CONFLICT", exception.getErrorCode());
100+
}
101+
102+
@Test
103+
void passwordExceptionSingleArgumentConstructor() {
104+
PasswordException exception = new PasswordException("bad password");
105+
106+
assertEquals("bad password", exception.getMessage());
107+
assertEquals(HttpStatus.BAD_REQUEST, exception.getHttpStatus());
108+
assertEquals("PASSWORD_ERROR", exception.getErrorCode());
109+
assertNull(exception.getCause());
110+
}
111+
112+
@Test
113+
void passwordExceptionMessageAndCauseConstructor() {
114+
RuntimeException cause = new RuntimeException("root");
115+
PasswordException exception = new PasswordException("bad password", cause);
116+
117+
assertEquals("bad password", exception.getMessage());
118+
assertEquals(HttpStatus.BAD_REQUEST, exception.getHttpStatus());
119+
assertEquals("PASSWORD_ERROR", exception.getErrorCode());
120+
assertSame(cause, exception.getCause());
121+
}
122+
123+
@Test
124+
void resourceNotFoundExceptionMessageConstructor() {
125+
ResourceNotFoundException exception = new ResourceNotFoundException("not found");
126+
127+
assertEquals("not found", exception.getMessage());
128+
assertEquals(HttpStatus.NOT_FOUND, exception.getHttpStatus());
129+
assertEquals("RESOURCE_NOT_FOUND", exception.getErrorCode());
130+
}
131+
132+
@Test
133+
void resourceNotFoundExceptionResourceTypeAndIdConstructor() {
134+
ResourceNotFoundException exception = new ResourceNotFoundException("User", 42L);
135+
136+
assertEquals("User not found with ID: 42", exception.getMessage());
137+
assertEquals(HttpStatus.NOT_FOUND, exception.getHttpStatus());
138+
assertEquals("RESOURCE_NOT_FOUND", exception.getErrorCode());
139+
}
140+
141+
@Test
142+
void resourceNotFoundExceptionResourceTypeAndIdentifierConstructor() {
143+
ResourceNotFoundException exception = new ResourceNotFoundException("User", "alice@example.com");
144+
145+
assertEquals("User not found: alice@example.com", exception.getMessage());
146+
assertEquals(HttpStatus.NOT_FOUND, exception.getHttpStatus());
147+
assertEquals("RESOURCE_NOT_FOUND", exception.getErrorCode());
148+
}
149+
150+
@Test
151+
void resourceNotFoundExceptionMessageAndCauseConstructor() {
152+
RuntimeException cause = new RuntimeException("root");
153+
ResourceNotFoundException exception = new ResourceNotFoundException("missing", cause);
154+
155+
assertEquals("missing", exception.getMessage());
156+
assertEquals(HttpStatus.NOT_FOUND, exception.getHttpStatus());
157+
assertEquals("RESOURCE_NOT_FOUND", exception.getErrorCode());
158+
assertSame(cause, exception.getCause());
159+
}
160+
161+
@Test
162+
void roleExceptionSingleArgumentConstructor() {
163+
RoleException exception = new RoleException("invalid role");
164+
165+
assertEquals("invalid role", exception.getMessage());
166+
assertEquals(HttpStatus.BAD_REQUEST, exception.getHttpStatus());
167+
assertEquals("ROLE_ERROR", exception.getErrorCode());
168+
assertNull(exception.getCause());
169+
}
170+
171+
@Test
172+
void roleExceptionMessageAndCauseConstructor() {
173+
RuntimeException cause = new RuntimeException("root");
174+
RoleException exception = new RoleException("invalid role", cause);
175+
176+
assertEquals("invalid role", exception.getMessage());
177+
assertEquals(HttpStatus.BAD_REQUEST, exception.getHttpStatus());
178+
assertEquals("ROLE_ERROR", exception.getErrorCode());
179+
assertSame(cause, exception.getCause());
180+
}
181+
182+
@Test
183+
void unitInactiveExceptionFormatsMessageAndMetadata() {
184+
UnitInactiveException exception = new UnitInactiveException(7L);
185+
186+
assertEquals("Temperature unit is inactive: 7", exception.getMessage());
187+
assertEquals(HttpStatus.CONFLICT, exception.getHttpStatus());
188+
assertEquals("UNIT_INACTIVE", exception.getErrorCode());
189+
}
190+
191+
@Test
192+
void unitNotFoundExceptionFormatsMessageAndMetadata() {
193+
UnitNotFoundException exception = new UnitNotFoundException(9L);
194+
195+
assertEquals("Temperature unit not found with id: 9", exception.getMessage());
196+
assertEquals(HttpStatus.NOT_FOUND, exception.getHttpStatus());
197+
assertEquals("UNIT_NOT_FOUND", exception.getErrorCode());
198+
}
199+
200+
@Test
201+
void userConflictExceptionSingleArgumentConstructor() {
202+
UserConflictException exception = new UserConflictException("duplicate user");
203+
204+
assertEquals("duplicate user", exception.getMessage());
205+
assertEquals(HttpStatus.CONFLICT, exception.getHttpStatus());
206+
assertEquals("USER_CONFLICT", exception.getErrorCode());
207+
assertNull(exception.getCause());
208+
}
209+
210+
@Test
211+
void userConflictExceptionMessageAndCauseConstructor() {
212+
RuntimeException cause = new RuntimeException("root");
213+
UserConflictException exception = new UserConflictException("duplicate user", cause);
214+
215+
assertEquals("duplicate user", exception.getMessage());
216+
assertEquals(HttpStatus.CONFLICT, exception.getHttpStatus());
217+
assertEquals("USER_CONFLICT", exception.getErrorCode());
218+
assertSame(cause, exception.getCause());
219+
}
220+
221+
private static final class TestAppException extends AppException {
222+
223+
private TestAppException(String message, HttpStatus httpStatus, String errorCode) {
224+
super(message, httpStatus, errorCode);
225+
}
226+
227+
private TestAppException(String message, Throwable cause, HttpStatus httpStatus, String errorCode) {
228+
super(message, cause, httpStatus, errorCode);
229+
}
230+
}
231+
}

0 commit comments

Comments
 (0)