Skip to content

Commit e2a3f1a

Browse files
committed
MODWRKFLOW-54: Migrate to Spring Boot 3.5.
The `folio-spring` dependency is actually using Spring Boot 4. Therefore, this only migrates enough to compile and run the unit tests. Bring in new controller advice testing practices that avoids needing to run a full Spring Boot service. The `count()` can no longer be used. Create a new `countAll()` with a `@Query` and utilize that.
1 parent 095b1d2 commit e2a3f1a

11 files changed

Lines changed: 227 additions & 149 deletions

File tree

service/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
<properties>
2020
<openapi.server.port>9000</openapi.server.port>
21-
<folio-spring.version>8.3.0-SNAPSHOT</folio-spring.version>
21+
<folio-spring.version>10.0.0</folio-spring.version>
2222
</properties>
2323

2424
<dependencies>
Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,8 @@
11
package org.folio.rest.workflow.config;
22

3-
import feign.okhttp.OkHttpClient;
4-
import org.springframework.context.annotation.Bean;
53
import org.springframework.context.annotation.Configuration;
64

75
@Configuration
86
public class OkHttpConfig {
97

10-
/**
11-
* Add feignOkHttpClient to prevent issues introduced when using folio-spring-base.
12-
*
13-
* The issue involves enrichUrlAndHeadersClient, FeignClientConfiguration, and okhttp3.OkHttpClient.
14-
*
15-
* This defines a bean of type 'okhttp3.OkHttpClient' to prevent the error.
16-
*/
17-
@Bean
18-
public OkHttpClient feignOkHttpClient() {
19-
return new OkHttpClient();
20-
}
21-
228
}

service/src/main/java/org/folio/rest/workflow/controller/advice/WorkflowControllerAdvice.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public ResponseEntity<String> handleWorkflowNotFoundException(WorkflowNotFoundEx
4848

4949
@ResponseStatus(HttpStatus.FORBIDDEN)
5050
@ExceptionHandler(WorkflowAlreadyActiveException.class)
51-
public ResponseEntity<String> handleWorkflowAlreadyActivrException(WorkflowAlreadyActiveException exception) {
51+
public ResponseEntity<String> handleWorkflowAlreadyActiveException(WorkflowAlreadyActiveException exception) {
5252
return buildError(exception, HttpStatus.FORBIDDEN);
5353
}
5454

@@ -66,7 +66,7 @@ public ResponseEntity<String> handleWorkflowEngineServiceException(WorkflowEngin
6666

6767
@ResponseStatus(HttpStatus.BAD_REQUEST)
6868
@ExceptionHandler(WorkflowImportException.class)
69-
public ResponseEntity<String> handleWorkflowImportExceptionException(WorkflowImportException exception) {
69+
public ResponseEntity<String> handleWorkflowImportException(WorkflowImportException exception) {
7070
return buildError(exception, HttpStatus.BAD_REQUEST);
7171
}
7272

service/src/main/java/org/folio/rest/workflow/model/repo/WorkflowRepo.java

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

33
import org.folio.rest.workflow.model.Workflow;
44
import org.folio.spring.cql.JpaCqlRepository;
5+
import org.springframework.data.jpa.repository.Query;
56
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
67
import org.springframework.data.rest.core.annotation.RestResource;
78

@@ -19,4 +20,7 @@ public interface WorkflowRepo extends JpaCqlRepository<Workflow, String> {
1920
@Override
2021
@RestResource(exported = false)
2122
public void deleteById(String id);
23+
24+
@Query("SELECT COUNT(*) FROM Workflow")
25+
public long countAll();
2226
}

service/src/main/java/org/folio/rest/workflow/service/WorkflowCqlService.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,25 +19,25 @@ public WorkflowCqlService(ObjectMapper mapper, WorkflowRepo repo) {
1919
this.repo = repo;
2020
}
2121

22-
@Override
23-
protected String getTypeName() {
24-
return Workflow.class.getSimpleName().toLowerCase() + "s";
25-
}
26-
2722
@Override
2823
public ObjectNode findByCql(String query, Long offset, Integer limit) {
2924
Page<Workflow> page = null;
3025
long total = 0;
3126

3227
if (StringUtils.isBlank(query)) {
3328
page = repo.findAll(new OffsetRequest(offset, limit));
34-
total = repo.count();
29+
total = repo.countAll();
3530
} else {
3631
page = repo.findByCql(query, new OffsetRequest(offset, limit));
37-
total = repo.count(query);
32+
total = repo.countByCql(query);
3833
}
3934

4035
return toJson(page.toList(), total);
4136
}
4237

38+
@Override
39+
protected String getTypeName() {
40+
return Workflow.class.getSimpleName().toLowerCase() + "s";
41+
}
42+
4343
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package org.folio.rest.workflow.config;
2+
3+
import com.fasterxml.jackson.databind.DeserializationFeature;
4+
import com.fasterxml.jackson.databind.ObjectMapper;
5+
import org.springframework.context.annotation.Bean;
6+
import org.springframework.context.annotation.TestConfiguration;
7+
import org.springframework.test.context.ActiveProfiles;
8+
9+
/**
10+
* Provide custom web MVC settings for use during unit tests.
11+
*/
12+
@TestConfiguration
13+
@ActiveProfiles("test")
14+
public class JunitHelperWebMvcConfig {
15+
16+
@Bean
17+
ObjectMapper objectMapper() {
18+
final ObjectMapper mapper = new ObjectMapper();
19+
20+
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
21+
22+
return mapper;
23+
}
24+
}
Lines changed: 44 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,98 +1,82 @@
11
package org.folio.rest.workflow.controller.advice;
22

3-
import static org.folio.spring.test.mock.MockMvcConstant.APP_JSON;
4-
import static org.folio.spring.test.mock.MockMvcConstant.JSON_OBJECT;
5-
import static org.folio.spring.test.mock.MockMvcConstant.OKAPI_HEAD;
63
import static org.folio.spring.test.mock.MockMvcConstant.VALUE;
7-
import static org.folio.spring.test.mock.MockMvcRequest.appendBody;
8-
import static org.folio.spring.test.mock.MockMvcRequest.appendHeaders;
4+
import static org.junit.jupiter.api.Assertions.assertEquals;
5+
import static org.junit.jupiter.api.Assertions.assertNotNull;
96
import static org.junit.jupiter.api.Assertions.assertTrue;
10-
import static org.mockito.ArgumentMatchers.any;
11-
import static org.mockito.BDDMockito.given;
12-
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
13-
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.log;
14-
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
157

168
import java.nio.file.FileSystemException;
179
import java.util.regex.Matcher;
1810
import java.util.regex.Pattern;
19-
import java.util.stream.Stream;
20-
import org.folio.rest.workflow.controller.EventController;
2111
import org.folio.rest.workflow.exception.EventPublishException;
2212
import org.junit.jupiter.api.BeforeEach;
13+
import org.junit.jupiter.api.Test;
2314
import org.junit.jupiter.api.extension.ExtendWith;
24-
import org.junit.jupiter.params.ParameterizedTest;
25-
import org.junit.jupiter.params.provider.Arguments;
26-
import org.junit.jupiter.params.provider.MethodSource;
27-
import org.mockito.Mock;
2815
import org.mockito.junit.jupiter.MockitoExtension;
29-
import org.springframework.beans.factory.annotation.Autowired;
30-
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
31-
import org.springframework.boot.test.context.SpringBootTest;
32-
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
16+
import org.springframework.http.HttpStatus;
17+
import org.springframework.http.MediaType;
18+
import org.springframework.http.ResponseEntity;
3319
import org.springframework.test.context.ActiveProfiles;
34-
import org.springframework.test.web.servlet.MockMvc;
35-
import org.springframework.test.web.servlet.MvcResult;
36-
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
37-
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
3820

39-
@SpringBootTest(webEnvironment = WebEnvironment.MOCK)
40-
@AutoConfigureMockMvc
4121
@ExtendWith(MockitoExtension.class)
4222
@ActiveProfiles("test")
4323
class EventControllerAdviceTest {
4424

45-
private static final String PATH = "/events";
25+
private static final Exception RUNTIME_EXC = new RuntimeException("Runtime failure.");
4626

47-
private static final String PATH_HANDLE = PATH + "/handle";
27+
private static final EventPublishException EP_EXC = new EventPublishException(VALUE, RUNTIME_EXC);
4828

49-
@Autowired
50-
private EventControllerAdvice eventControllerAdvice;
29+
private static final FileSystemException FS_EXC = new FileSystemException(VALUE);
5130

52-
@Autowired
53-
@Mock
54-
private EventController eventController;
55-
56-
private MockMvc mvc;
31+
private EventControllerAdvice advice;
5732

5833
@BeforeEach
5934
void beforeEach() {
60-
mvc = MockMvcBuilders.standaloneSetup(eventController)
61-
.setControllerAdvice(eventControllerAdvice)
62-
.build();
35+
advice = new EventControllerAdvice();
36+
}
37+
38+
@Test
39+
void handleEventPublishExceptionTest() {
40+
41+
final String simpleName = EventPublishException.class.getSimpleName();
42+
final ResponseEntity<String> response = advice.handleEventPublishException(EP_EXC);
43+
44+
assertNotNull(response);
45+
assertNotNull(response.getBody());
46+
47+
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode());
48+
assertEquals(MediaType.APPLICATION_JSON, response.getHeaders().getContentType());
49+
assertTrue(matchBody(response, simpleName));
6350
}
6451

65-
@ParameterizedTest
66-
@MethodSource("provideExceptionsToMatchForActivateWorkflow")
67-
void exceptionsThrownForActivateWorkflowTest(Exception exception, String simpleName, int status) throws Exception {
68-
given(eventController.postHandleEvents(any(), any())).willAnswer(invocation -> { throw exception; });
52+
@Test
53+
void handleFileSystemExceptionTest() {
6954

70-
MockHttpServletRequestBuilder request = appendHeaders(post(PATH_HANDLE), OKAPI_HEAD, APP_JSON, APP_JSON);
55+
final String simpleName = FileSystemException.class.getSimpleName();
56+
final ResponseEntity<String> response = advice.handleFileSystemException(FS_EXC);
7157

72-
MvcResult result = mvc.perform(appendBody(request, JSON_OBJECT))
73-
.andDo(log()).andExpect(status().is(status)).andReturn();
58+
assertNotNull(response);
59+
assertNotNull(response.getBody());
7460

75-
Pattern pattern = Pattern.compile("\"type\":\"" + simpleName + "\"");
76-
Matcher matcher = pattern.matcher(result.getResponse().getContentAsString());
77-
assertTrue(matcher.find());
61+
assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());
62+
assertEquals(MediaType.APPLICATION_JSON, response.getHeaders().getContentType());
63+
assertTrue(matchBody(response, simpleName));
7864
}
7965

8066
/**
81-
* Helper function for parameterized test providing the exceptions to be matched for activate workflow.
67+
* Match the class simple name in the response.
8268
*
83-
* @return
84-
* The arguments array stream with the stream columns as:
85-
* - Exception exception.
86-
* - String simpleName (exception name to match).
87-
* - int status (response HTTP status code for the exception).
69+
* @param response The response to search.
70+
* @param simpleName The class name to match.
71+
*
72+
* @return TRUE on match; FALSE otherwise.
8873
*/
89-
private static Stream<Arguments> provideExceptionsToMatchForActivateWorkflow() {
90-
Exception runtime = new RuntimeException("Runtime failure.");
74+
private boolean matchBody(ResponseEntity<String> response, String simpleName) {
75+
76+
final Pattern pattern = Pattern.compile("\"type\":\"" + simpleName + "\"");
77+
final Matcher matcher = pattern.matcher(response.getBody());
9178

92-
return Stream.of(
93-
Arguments.of(new EventPublishException(VALUE, runtime), EventPublishException.class.getSimpleName(), 500),
94-
Arguments.of(new FileSystemException(VALUE), FileSystemException.class.getSimpleName(), 400)
95-
);
79+
return matcher.find();
9680
}
9781

9882
}

0 commit comments

Comments
 (0)