Skip to content

Commit 19a93a5

Browse files
Merge pull request #24 from hmcts/openapi-update
update integration test; enhance error handling responses
2 parents 088f360 + 4acb154 commit 19a93a5

File tree

16 files changed

+377
-195
lines changed

16 files changed

+377
-195
lines changed

.github/workflows/ci-draft.yml

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -143,22 +143,22 @@ jobs:
143143
BASE_IMAGE=openjdk:21-jdk-slim
144144
JAR_FILENAME=${{ needs.Build.outputs.artefact_name }}.jar
145145
146-
# https://github.com/marketplace/actions/azure-pipelines-action
147-
Deploy:
148-
needs: [ Build, Artefact-Version ]
149-
runs-on: ubuntu-latest
150-
if: github.event_name == 'push'
151-
152-
steps:
153-
- name: Trigger ADO pipeline
154-
uses: Azure/pipelines@v1.2
155-
with:
156-
azure-devops-project-url: 'https://dev.azure.com/hmcts-cpp/cpp-apps'
157-
azure-pipeline-name: 'cp-gh-artifact-to-acr'
158-
azure-devops-token: ${{ secrets.HMCTS_ADO_PAT }}
159-
azure-pipeline-variables: >-
160-
{
161-
"GROUP_ID" : "uk.gov.hmcts.cp",
162-
"ARTIFACT_ID" : "${{ github.repository }}",
163-
"ARTIFACT_VERSION" : "${{ needs.Artefact-Version.outputs.draft_version}}"
164-
}
146+
# # https://github.com/marketplace/actions/azure-pipelines-action
147+
# Deploy:
148+
# needs: [ Build, Artefact-Version ]
149+
# runs-on: ubuntu-latest
150+
# if: github.event_name == 'push'
151+
#
152+
# steps:
153+
# - name: Trigger ADO pipeline
154+
# uses: Azure/pipelines@v1.2
155+
# with:
156+
# azure-devops-project-url: 'https://dev.azure.com/hmcts-cpp/cpp-apps'
157+
# azure-pipeline-name: 'cp-gh-artifact-to-acr'
158+
# azure-devops-token: ${{ secrets.HMCTS_ADO_PAT }}
159+
# azure-pipeline-variables: >-
160+
# {
161+
# "GROUP_ID" : "uk.gov.hmcts.cp",
162+
# "ARTIFACT_ID" : "${{ github.repository }}",
163+
# "ARTIFACT_VERSION" : "${{ needs.Artefact-Version.outputs.draft_version}}"
164+
# }

build.gradle

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@ configurations {
6262

6363
integrationTestImplementation.extendsFrom testImplementation
6464
integrationTestRuntimeOnly.extendsFrom runtimeOnly
65+
66+
// Ensure testRuntimeClasspath can be resolved for agent injection
67+
testRuntimeClasspath {
68+
canBeResolved = true
69+
}
6570
}
6671

6772

@@ -78,6 +83,11 @@ tasks.named('test') {
7883
useJUnitPlatform()
7984
systemProperty 'API_SPEC_VERSION', project.version
8085
failFast = true
86+
// Mockito must be added as an agent, see:
87+
// https://javadoc.io/doc/org.mockito/mockito-core/latest/org.mockito/org/mockito/Mockito.html#0.3
88+
jvmArgs += [
89+
"-javaagent:${configurations.testRuntimeClasspath.find { it.name.contains('mockito-core') }}", '-Xshare:off'
90+
]
8191
testLogging {
8292
events "passed", "skipped", "failed"
8393
exceptionFormat = 'full'
@@ -94,14 +104,40 @@ tasks.register('functional', Test) {
94104
group = "Verification"
95105
testClassesDirs = sourceSets.functionalTest.output.classesDirs
96106
classpath = sourceSets.functionalTest.runtimeClasspath
107+
useJUnitPlatform()
108+
failFast = true
109+
testLogging {
110+
events "passed", "skipped", "failed"
111+
exceptionFormat = 'full'
112+
showStandardStreams = true
113+
}
114+
reports {
115+
junitXml.required.set(true) // For CI tools (e.g. Jenkins, GitHub Actions)
116+
html.required.set(true) // Human-readable browser report
117+
}
97118
}
98-
99119
tasks.register('integration', Test) {
100120
description = "Runs integration tests"
101121
group = "Verification"
102122
testClassesDirs = sourceSets.integrationTest.output.classesDirs
103123
classpath = sourceSets.integrationTest.runtimeClasspath
124+
useJUnitPlatform()
104125
failFast = true
126+
testLogging {
127+
events "passed", "skipped", "failed"
128+
exceptionFormat = 'full'
129+
showStandardStreams = true
130+
}
131+
reports {
132+
junitXml.required.set(true) // For CI tools (e.g. Jenkins, GitHub Actions)
133+
html.required.set(true) // Human-readable browser report
134+
}
135+
}
136+
137+
tasks.named('build') {
138+
dependsOn tasks.named('test')
139+
dependsOn tasks.named('integration')
140+
// dependsOn tasks.named('functional') disabling until functional tests are implemented
105141
}
106142

107143
tasks.named('jacocoTestReport') {
@@ -113,11 +149,6 @@ tasks.named('jacocoTestReport') {
113149
}
114150
}
115151

116-
tasks.named('check') {
117-
dependsOn tasks.named('integration')
118-
dependsOn tasks.named('functional')
119-
}
120-
121152
// check dependencies upon release ONLY
122153
tasks.named("dependencyUpdates").configure {
123154
def isNonStable = { String version ->
@@ -200,7 +231,7 @@ application {
200231
}
201232

202233
ext {
203-
apiCourtScheduleVersion="0.3.0"
234+
apiCourtScheduleVersion = "0.3.3"
204235
log4JVersion = "2.24.3"
205236
logbackVersion = "1.5.18"
206237
lombokVersion = "1.18.38"
@@ -216,8 +247,11 @@ dependencies {
216247
implementation 'org.springframework.boot:spring-boot-starter-aop'
217248
implementation 'org.springframework.boot:spring-boot-starter-json'
218249

219-
implementation 'org.springframework.cloud:spring-cloud-starter-sleuth:3.1.11'
220-
implementation 'com.azure.spring:spring-cloud-azure-trace-sleuth:4.20.0'
250+
implementation platform('io.micrometer:micrometer-tracing-bom:latest.release')
251+
implementation 'io.micrometer:micrometer-tracing'
252+
implementation 'io.micrometer:micrometer-tracing-bridge-otel'
253+
implementation 'io.micrometer:micrometer-registry-azure-monitor'
254+
implementation 'com.azure:azure-monitor-opentelemetry-exporter:1.0.0-beta.17'
221255

222256
implementation 'net.logstash.logback:logstash-logback-encoder:8.1'
223257
implementation group: 'org.apache.logging.log4j', name: 'log4j-to-slf4j', version: log4JVersion
@@ -232,6 +266,8 @@ dependencies {
232266
annotationProcessor group: 'org.projectlombok', name: 'lombok', version: lombokVersion
233267

234268
testImplementation(platform('org.junit:junit-bom:5.12.2'))
269+
testImplementation 'org.mockito:mockito-core:5.18.0'
270+
testRuntimeOnly 'org.mockito:mockito-inline:5.2.0'
235271
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
236272
testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: '3.5.0', {
237273
exclude group: 'junit', module: 'junit'

src/functionalTest/java/uk/gov/hmcts/cp/controllers/SampleFunctionalTest.java

Lines changed: 0 additions & 39 deletions
This file was deleted.
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package uk.gov.hmcts.cp.controllers;
2+
3+
import com.fasterxml.jackson.databind.JsonNode;
4+
import com.fasterxml.jackson.databind.ObjectMapper;
5+
import org.junit.jupiter.api.Test;
6+
import org.junit.jupiter.api.extension.ExtendWith;
7+
import org.slf4j.Logger;
8+
import org.slf4j.LoggerFactory;
9+
import org.springframework.beans.factory.annotation.Autowired;
10+
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
11+
import org.springframework.boot.test.context.SpringBootTest;
12+
import org.springframework.http.MediaType;
13+
import org.springframework.test.context.junit.jupiter.SpringExtension;
14+
import org.springframework.test.web.servlet.MockMvc;
15+
import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponse;
16+
17+
import java.util.UUID;
18+
19+
import static org.junit.jupiter.api.Assertions.*;
20+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
21+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
22+
23+
@ExtendWith(SpringExtension.class)
24+
@SpringBootTest
25+
@AutoConfigureMockMvc
26+
class CourtScheduleControllerIT {
27+
private static final Logger log = LoggerFactory.getLogger(CourtScheduleControllerIT.class);
28+
29+
@Autowired
30+
private MockMvc mockMvc;
31+
32+
@Test
33+
void shouldReturnOkWhenValidUrnIsProvided() throws Exception {
34+
String caseUrn = "test-case-urn";
35+
CourtScheduleResponse expectedResponse = CourtScheduleResponse.builder().build();
36+
37+
mockMvc.perform(get("/case/{case_urn}/courtschedule", caseUrn)
38+
.accept(MediaType.APPLICATION_JSON))
39+
.andExpect(status().isOk())
40+
.andExpect(result -> {
41+
// You may need to adjust this depending on the actual fields in CourtScheduleResponse
42+
String responseBody = result.getResponse().getContentAsString();
43+
log.info("Response: {}", responseBody);
44+
JsonNode jsonBody = new ObjectMapper().readTree(result.getResponse().getContentAsString());
45+
46+
47+
assertEquals("courtSchedule", jsonBody.fieldNames().next());
48+
JsonNode courtSchedule = jsonBody.get("courtSchedule");
49+
assertTrue(courtSchedule.isArray());
50+
assertEquals(1, courtSchedule.size());
51+
52+
JsonNode hearings = courtSchedule.get(0).get("hearings");
53+
assertTrue(hearings.isArray());
54+
assertEquals(1, hearings.size());
55+
56+
JsonNode hearing = hearings.get(0);
57+
UUID hearingId = UUID.fromString(hearing.get("hearingId").asText());
58+
assertNotNull(hearingId);
59+
assertEquals("Requires interpreter", hearing.get("listNote").asText());
60+
assertEquals("Sentencing for theft case", hearing.get("hearingDescription").asText());
61+
assertEquals("Trial", hearing.get("hearingType").asText());
62+
63+
JsonNode courtSittings = hearing.get("courtSittings");
64+
assertTrue(courtSittings.isArray());
65+
assertEquals(1, courtSittings.size());
66+
67+
JsonNode sitting = courtSittings.get(0);
68+
assertEquals("Central Criminal Court", sitting.get("courtHouse").asText());
69+
assertNotNull(sitting.get("sittingStart").asText());
70+
assertNotNull(sitting.get("sittingEnd").asText());
71+
UUID judiciaryId = UUID.fromString(sitting.get("judiciaryId").asText());
72+
assertNotNull(sitting.get("judiciaryId").asText());
73+
log.info("Response Object: {}", jsonBody);
74+
});
75+
}
76+
}

src/integrationTest/java/uk/gov/hmcts/cp/controllers/CourtScheduleControllerITest.java

Lines changed: 0 additions & 31 deletions
This file was deleted.

src/integrationTest/java/uk/gov/hmcts/cp/controllers/RootControllerIntegrationTest.java renamed to src/integrationTest/java/uk/gov/hmcts/cp/controllers/RootControllerIntegrationIT.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
@ExtendWith(SpringExtension.class)
2020
@SpringBootTest
2121
@AutoConfigureMockMvc
22-
class RootControllerIntegrationTest {
22+
class RootControllerIntegrationIT {
2323

2424
@Autowired
2525
private MockMvc mockMvc;

src/integrationTest/java/uk/gov/hmcts/cp/openapi/OpenAPIPublisherTest.java

Lines changed: 0 additions & 49 deletions
This file was deleted.

src/main/java/uk/gov/hmcts/cp/controllers/CourtScheduleController.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import org.slf4j.Logger;
55
import org.slf4j.LoggerFactory;
66
import org.springframework.http.HttpStatus;
7+
import org.springframework.http.MediaType;
78
import org.springframework.http.ResponseEntity;
89
import org.springframework.web.bind.annotation.RestController;
910
import org.springframework.web.server.ResponseStatusException;
@@ -26,17 +27,19 @@ public ResponseEntity<CourtScheduleResponse> getCourtScheduleByCaseUrn(String ca
2627
CourtScheduleResponse courtScheduleResponse;
2728
try {
2829
sanitizedCaseUrn = sanitizeCaseUrn(caseUrn);
29-
courtScheduleResponse = courtScheduleService.getCourtScheduleResponse(sanitizedCaseUrn);
30+
courtScheduleResponse = courtScheduleService.getCourtScheduleByCaseUrn(sanitizedCaseUrn);
3031
} catch (ResponseStatusException e) {
3132
log.error(e.getMessage());
32-
return ResponseEntity.status(e.getStatusCode()).build();
33+
throw e;
3334
}
3435
log.debug("Found court schedule for caseUrn: {}", sanitizedCaseUrn);
35-
return new ResponseEntity<>(courtScheduleResponse, HttpStatus.OK);
36+
return ResponseEntity.ok()
37+
.contentType(MediaType.APPLICATION_JSON)
38+
.body(courtScheduleResponse);
3639
}
3740

3841
private String sanitizeCaseUrn(String urn) {
39-
if (urn == null) throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "caseUrn is required");;
42+
if (urn == null) throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "caseUrn is required");
4043
return StringEscapeUtils.escapeHtml4(urn);
4144
}
4245
}

0 commit comments

Comments
 (0)