Skip to content

Commit 48ab785

Browse files
ChrisEdwardsclaude
andcommitted
Add assertj library and convert test assertions (AIML-231)
- Added assertj-core 3.27.6 dependency to pom.xml with test scope - Converted ~894 JUnit assertions to AssertJ fluent API across 20 test files - Updated imports from org.junit.jupiter.api.Assertions to org.assertj.core.api.Assertions - Applied conversion patterns: * assertEquals(expected, actual) → assertThat(actual).isEqualTo(expected) * assertTrue(condition) → assertThat(condition).isTrue() * assertFalse(condition) → assertThat(condition).isFalse() * assertNull(value) → assertThat(value).isNull() * assertNotNull(value) → assertThat(value).isNotNull() * assertThrows() → assertThatThrownBy().isInstanceOf() - Documented AssertJ usage standard in CLAUDE.md Coding Standards section - All 250 tests pass successfully Benefits: - More readable, fluent assertion syntax - Better error messages when tests fail - Richer assertion API (isEmpty(), hasSize(), contains(), etc.) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 2aa0872 commit 48ab785

23 files changed

+1853
-1251
lines changed

CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ Required environment variables/arguments:
8282
- **Use `isEmpty()`** instead of `size() > 0` or `size() == 0` for collection checks
8383
- **No wildcard imports** - All imports must be explicit. Do not use `import package.*` syntax
8484
- **Simplified mock() syntax** - Use `mock()` without class parameter (Mockito 5.x+). When using `var`, specify the type explicitly: `ClassName mock = mock();` instead of `var mock = mock(ClassName.class);`. For explicit types: `ClassName mock = mock();` instead of `ClassName mock = mock(ClassName.class);`
85+
- **Use AssertJ for test assertions** - Prefer AssertJ's fluent API over JUnit assertions for more readable and expressive tests. Use `assertThat(actual).isEqualTo(expected)` instead of `assertEquals(expected, actual)`, and `assertThat(condition).isTrue()` instead of `assertTrue(condition)`
8586

8687
### Security Considerations
8788

pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@
5757
<artifactId>spring-boot-starter-test</artifactId>
5858
<scope>test</scope>
5959
</dependency>
60+
<dependency>
61+
<groupId>org.assertj</groupId>
62+
<artifactId>assertj-core</artifactId>
63+
<version>3.27.6</version>
64+
<scope>test</scope>
65+
</dependency>
6066
</dependencies>
6167
<dependencyManagement>
6268
<dependencies>

src/test/java/com/contrast/labs/ai/mcp/contrast/ADRServiceIntegrationTest.java

Lines changed: 30 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
*/
1616
package com.contrast.labs.ai.mcp.contrast;
1717

18-
import static org.junit.jupiter.api.Assertions.*;
18+
import static org.assertj.core.api.Assertions.assertThat;
19+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
20+
import static org.assertj.core.api.Assertions.fail;
1921

2022
import com.contrast.labs.ai.mcp.contrast.sdkextension.SDKExtension;
2123
import com.contrast.labs.ai.mcp.contrast.sdkextension.SDKHelper;
@@ -254,10 +256,12 @@ private String buildTestDataErrorMessage(int appsChecked) {
254256
void testDiscoveredTestDataExists() {
255257
log.info("\n=== Integration Test: Validate test data discovery ===");
256258

257-
assertNotNull(testData, "Test data should have been discovered in @BeforeAll");
258-
assertNotNull(testData.appId, "Test application ID should be set");
259-
assertTrue(testData.hasProtectRules, "Test application should have Protect rules");
260-
assertTrue(testData.ruleCount > 0, "Test application should have at least 1 rule");
259+
assertThat(testData).as("Test data should have been discovered in @BeforeAll").isNotNull();
260+
assertThat(testData.appId).as("Test application ID should be set").isNotNull();
261+
assertThat(testData.hasProtectRules).as("Test application should have Protect rules").isTrue();
262+
assertThat(testData.ruleCount)
263+
.as("Test application should have at least 1 rule")
264+
.isGreaterThan(0);
261265

262266
log.info("✓ Test data validated:");
263267
log.info(" App ID: {}", testData.appId);
@@ -271,15 +275,15 @@ void testDiscoveredTestDataExists() {
271275
void testGetADRProtectRules_Success() throws IOException {
272276
log.info("\n=== Integration Test: get_ADR_Protect_Rules_by_app_id ===");
273277

274-
assertNotNull(testData, "Test data must be discovered before running tests");
278+
assertThat(testData).as("Test data must be discovered before running tests").isNotNull();
275279

276280
// Act
277281
var response = adrService.getProtectDataByAppID(testData.appId);
278282

279283
// Assert
280-
assertNotNull(response, "Response should not be null");
281-
assertNotNull(response.getRules(), "Rules should not be null");
282-
assertTrue(response.getRules().size() > 0, "Should have at least 1 rule");
284+
assertThat(response).as("Response should not be null").isNotNull();
285+
assertThat(response.getRules()).as("Rules should not be null").isNotNull();
286+
assertThat(response.getRules().size()).as("Should have at least 1 rule").isGreaterThan(0);
283287

284288
log.info(
285289
"✓ Retrieved "
@@ -296,7 +300,7 @@ void testGetADRProtectRules_Success() throws IOException {
296300

297301
// Verify rule structure
298302
for (var rule : response.getRules()) {
299-
assertNotNull(rule.getName(), "Rule name should not be null");
303+
assertThat(rule.getName()).as("Rule name should not be null").isNotNull();
300304
// Production mode might be null, block, monitor, or off
301305
// Just verify the field exists (can be null for non-production rules)
302306
}
@@ -332,49 +336,39 @@ void testGetADRProtectRules_InvalidAppId() {
332336
}
333337

334338
// Either exception or graceful handling is acceptable
335-
assertTrue(true, "Test passes if either exception thrown or graceful handling occurs");
339+
assertThat(true)
340+
.as("Test passes if either exception thrown or graceful handling occurs")
341+
.isTrue();
336342
}
337343

338344
@Test
339345
void testGetADRProtectRules_NullAppId() {
340346
log.info("\n=== Integration Test: Null app ID handling ===");
341347

342348
// Act/Assert - Should throw IllegalArgumentException
343-
var exception =
344-
assertThrows(
345-
IllegalArgumentException.class,
349+
assertThatThrownBy(
346350
() -> {
347351
adrService.getProtectDataByAppID(null);
348-
});
352+
})
353+
.isInstanceOf(IllegalArgumentException.class)
354+
.hasMessageContaining("Application ID cannot be null or empty");
349355

350356
log.info("✓ Null app ID correctly rejected");
351-
log.info(" Exception: {}", exception.getClass().getSimpleName());
352-
log.info(" Message: {}", exception.getMessage());
353-
354-
assertTrue(
355-
exception.getMessage().contains("Application ID cannot be null or empty"),
356-
"Exception message should explain the validation failure");
357357
}
358358

359359
@Test
360360
void testGetADRProtectRules_EmptyAppId() {
361361
log.info("\n=== Integration Test: Empty app ID handling ===");
362362

363363
// Act/Assert - Should throw IllegalArgumentException
364-
var exception =
365-
assertThrows(
366-
IllegalArgumentException.class,
364+
assertThatThrownBy(
367365
() -> {
368366
adrService.getProtectDataByAppID("");
369-
});
367+
})
368+
.isInstanceOf(IllegalArgumentException.class)
369+
.hasMessageContaining("Application ID cannot be null or empty");
370370

371371
log.info("✓ Empty app ID correctly rejected");
372-
log.info(" Exception: {}", exception.getClass().getSimpleName());
373-
log.info(" Message: {}", exception.getMessage());
374-
375-
assertTrue(
376-
exception.getMessage().contains("Application ID cannot be null or empty"),
377-
"Exception message should explain the validation failure");
378372
}
379373

380374
// ========== Test Case 4: Rule Details Verification ==========
@@ -383,15 +377,15 @@ void testGetADRProtectRules_EmptyAppId() {
383377
void testGetADRProtectRules_VerifyRuleDetails() throws IOException {
384378
log.info("\n=== Integration Test: Verify rule details structure ===");
385379

386-
assertNotNull(testData, "Test data must be discovered before running tests");
380+
assertThat(testData).as("Test data must be discovered before running tests").isNotNull();
387381

388382
// Act
389383
var response = adrService.getProtectDataByAppID(testData.appId);
390384

391385
// Assert
392-
assertNotNull(response);
393-
assertNotNull(response.getRules());
394-
assertFalse(response.getRules().isEmpty());
386+
assertThat(response).isNotNull();
387+
assertThat(response.getRules()).isNotNull();
388+
assertThat(response.getRules()).isNotEmpty();
395389

396390
log.info("✓ Verifying rule details for {}", response.getRules().size() + " rules:");
397391

@@ -400,7 +394,7 @@ void testGetADRProtectRules_VerifyRuleDetails() throws IOException {
400394
log.info("\n Rule: {}", rule.getName());
401395

402396
// Verify required fields
403-
assertNotNull(rule.getName(), "Rule name is required");
397+
assertThat(rule.getName()).as("Rule name is required").isNotNull();
404398

405399
log.info(" ✓ Name: {}", rule.getName());
406400
if (rule.getProduction() != null) {

0 commit comments

Comments
 (0)