mirror of
https://github.com/spring-projects/spring-petclinic.git
synced 2025-07-25 01:05:48 +00:00
Merge branch 'spring-projects:main' into main
This commit is contained in:
commit
15843c8a48
4 changed files with 208 additions and 38 deletions
|
@ -8,6 +8,6 @@ ARG USER=vscode
|
|||
VOLUME /home/$USER/.m2
|
||||
VOLUME /home/$USER/.gradle
|
||||
|
||||
ARG JAVA_VERSION=17.0.4.1-ms
|
||||
ARG JAVA_VERSION=17.0.7-ms
|
||||
RUN sudo mkdir /home/$USER/.m2 /home/$USER/.gradle && sudo chown $USER:$USER /home/$USER/.m2 /home/$USER/.gradle
|
||||
RUN bash -lc '. /usr/local/sdkman/bin/sdkman-init.sh && sdk install java $JAVA_VERSION && sdk use java $JAVA_VERSION'
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.samples.petclinic.system;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.RequestEntity;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
/**
|
||||
* Integration Test for {@link CrashController}.
|
||||
*
|
||||
* @author Alex Lutz
|
||||
*/
|
||||
// NOT Waiting https://github.com/spring-projects/spring-boot/issues/5574
|
||||
@SpringBootTest(webEnvironment = RANDOM_PORT,
|
||||
properties = { "server.error.include-message=ALWAYS", "management.endpoints.enabled-by-default=false" })
|
||||
class CrashControllerIntegrationTests {
|
||||
|
||||
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class,
|
||||
DataSourceTransactionManagerAutoConfiguration.class, HibernateJpaAutoConfiguration.class })
|
||||
static class TestConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Value(value = "${local.server.port}")
|
||||
private int port;
|
||||
|
||||
@Autowired
|
||||
private TestRestTemplate rest;
|
||||
|
||||
@Test
|
||||
void testTriggerExceptionJson() {
|
||||
ResponseEntity<Map<String, Object>> resp = rest.exchange(
|
||||
RequestEntity.get("http://localhost:" + port + "/oups").build(),
|
||||
new ParameterizedTypeReference<Map<String, Object>>() {
|
||||
});
|
||||
assertThat(resp).isNotNull();
|
||||
assertThat(resp.getStatusCode().is5xxServerError());
|
||||
assertThat(resp.getBody().containsKey("timestamp"));
|
||||
assertThat(resp.getBody().containsKey("status"));
|
||||
assertThat(resp.getBody().containsKey("error"));
|
||||
assertThat(resp.getBody()).containsEntry("message",
|
||||
"Expected: controller used to showcase what happens when an exception is thrown");
|
||||
assertThat(resp.getBody()).containsEntry("path", "/oups");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTriggerExceptionHtml() {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setAccept(List.of(MediaType.TEXT_HTML));
|
||||
ResponseEntity<String> resp = rest.exchange("http://localhost:" + port + "/oups", HttpMethod.GET,
|
||||
new HttpEntity<>(headers), String.class);
|
||||
assertThat(resp).isNotNull();
|
||||
assertThat(resp.getStatusCode().is5xxServerError());
|
||||
assertThat(resp.getBody()).isNotNull();
|
||||
// html:
|
||||
assertThat(resp.getBody()).containsSubsequence("<body>", "<h2>", "Something happened...", "</h2>", "<p>",
|
||||
"Expected:", "controller", "used", "to", "showcase", "what", "happens", "when", "an", "exception", "is",
|
||||
"thrown", "</p>", "</body>");
|
||||
// Not the whitelabel error page:
|
||||
assertThat(resp.getBody()).doesNotContain("Whitelabel Error Page",
|
||||
"This application has no explicit mapping for");
|
||||
}
|
||||
|
||||
}
|
|
@ -16,35 +16,31 @@
|
|||
|
||||
package org.springframework.samples.petclinic.system;
|
||||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Test class for {@link CrashController}
|
||||
*
|
||||
* @author Colin But
|
||||
* @author Alex Lutz
|
||||
*/
|
||||
// Waiting https://github.com/spring-projects/spring-boot/issues/5574
|
||||
@Disabled
|
||||
@WebMvcTest(controllers = CrashController.class)
|
||||
// Waiting https://github.com/spring-projects/spring-boot/issues/5574 ..good
|
||||
// luck ((plain(st) UNIT test)! :)
|
||||
class CrashControllerTests {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
CrashController testee = new CrashController();
|
||||
|
||||
@Test
|
||||
void testTriggerException() throws Exception {
|
||||
mockMvc.perform(get("/oups"))
|
||||
.andExpect(view().name("exception"))
|
||||
.andExpect(model().attributeExists("exception"))
|
||||
.andExpect(forwardedUrl("exception"))
|
||||
.andExpect(status().isOk());
|
||||
RuntimeException thrown = assertThrows(RuntimeException.class, () -> {
|
||||
testee.triggerException();
|
||||
});
|
||||
|
||||
assertEquals("Expected: controller used to showcase what happens when an exception is thrown",
|
||||
thrown.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<jmeterTestPlan version="1.2" properties="2.8" jmeter="2.13 r1665067">
|
||||
<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.5">
|
||||
<hashTree>
|
||||
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true">
|
||||
<stringProp name="TestPlan.comments"></stringProp>
|
||||
|
@ -69,7 +69,7 @@
|
|||
<hashTree/>
|
||||
<CounterConfig guiclass="CounterConfigGui" testclass="CounterConfig" testname="User Count" enabled="true">
|
||||
<stringProp name="CounterConfig.start">1</stringProp>
|
||||
<stringProp name="CounterConfig.end">10</stringProp>
|
||||
<stringProp name="CounterConfig.end">3</stringProp>
|
||||
<stringProp name="CounterConfig.incr">1</stringProp>
|
||||
<stringProp name="CounterConfig.name">count</stringProp>
|
||||
<stringProp name="CounterConfig.format"></stringProp>
|
||||
|
@ -78,7 +78,7 @@
|
|||
<hashTree/>
|
||||
<CounterConfig guiclass="CounterConfigGui" testclass="CounterConfig" testname="Pet Count" enabled="true">
|
||||
<stringProp name="CounterConfig.start">1</stringProp>
|
||||
<stringProp name="CounterConfig.end">13</stringProp>
|
||||
<stringProp name="CounterConfig.end">3</stringProp>
|
||||
<stringProp name="CounterConfig.incr">1</stringProp>
|
||||
<stringProp name="CounterConfig.name">petCount</stringProp>
|
||||
<stringProp name="CounterConfig.format"></stringProp>
|
||||
|
@ -135,7 +135,7 @@
|
|||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">${CONTEXT_WEB}/webjars/jquery/jquery.min.js</stringProp>
|
||||
<stringProp name="HTTPSampler.path">${CONTEXT_WEB}/webjars/bootstrap/5.2.3/dist/js/bootstrap.bundle.min.js</stringProp>
|
||||
<stringProp name="HTTPSampler.method">GET</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
|
@ -246,13 +246,42 @@
|
|||
</HTTPSamplerProxy>
|
||||
<hashTree/>
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="POST Edit Owner" enabled="true">
|
||||
<boolProp name="HTTPSampler.postBodyRaw">true</boolProp>
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="Variables pr<70>-d<>finies" enabled="true">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="" elementType="HTTPArgument">
|
||||
<elementProp name="firstName" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">firstName=Test&lastName=${count}&address=1234+Test+St.&city=TestCity&telephone=612345678</stringProp>
|
||||
<stringProp name="Argument.value">Test</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">firstName</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="lastName" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">${count}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">lastName</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="address" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">1234+Test+St.</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">address</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="city" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">TestCity</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">city</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="telephone" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">612345678</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">telephone</stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</elementProp>
|
||||
|
@ -272,7 +301,7 @@
|
|||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree/>
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="New visit" enabled="true">
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="New Pet" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="Variables pr<70>-d<>finies" enabled="true">
|
||||
<collectionProp name="Arguments.arguments"/>
|
||||
</elementProp>
|
||||
|
@ -282,7 +311,7 @@
|
|||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">${CONTEXT_WEB}/owners/${count}/pets/${petCount}/visits/new</stringProp>
|
||||
<stringProp name="HTTPSampler.path">${CONTEXT_WEB}/owners/${count}/pets/new</stringProp>
|
||||
<stringProp name="HTTPSampler.method">GET</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
|
@ -292,14 +321,29 @@
|
|||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree/>
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="POST new visit" enabled="true">
|
||||
<boolProp name="HTTPSampler.postBodyRaw">true</boolProp>
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments">
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="POST new pet" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="Variables pr<70>-d<>finies" enabled="true">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="" elementType="HTTPArgument">
|
||||
<elementProp name="name" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">date=2013%2F02%2F22&description=visit</stringProp>
|
||||
<stringProp name="Argument.value">Test+Fluffy+${petCount}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">name</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="birthDate" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">2020-12-20</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">birthDate</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="type" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">cat</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">type</stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</elementProp>
|
||||
|
@ -309,7 +353,7 @@
|
|||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">${CONTEXT_WEB}/owners/${count}/pets/${petCount}/visits/new</stringProp>
|
||||
<stringProp name="HTTPSampler.path">${CONTEXT_WEB}/owners/${count}/pets/new</stringProp>
|
||||
<stringProp name="HTTPSampler.method">POST</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
|
@ -319,22 +363,54 @@
|
|||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree/>
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Owner" enabled="true">
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="New visit" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="Variables pr<70>-d<>finies" enabled="true">
|
||||
<collectionProp name="Arguments.arguments"/>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain"></stringProp>
|
||||
<stringProp name="HTTPSampler.port"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">${CONTEXT_WEB}/owners/${count}</stringProp>
|
||||
<stringProp name="HTTPSampler.path">${CONTEXT_WEB}/owners/${count}/pets/${petCount}/visits/new</stringProp>
|
||||
<stringProp name="HTTPSampler.method">GET</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree/>
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="POST new visit" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="Variables pr<70>-d<>finies" enabled="true">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="date" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">2013-02-22</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">date</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="description" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">visit</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">description</stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain"></stringProp>
|
||||
<stringProp name="HTTPSampler.port"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">${CONTEXT_WEB}/owners/${count}/pets/${petCount}/visits/new</stringProp>
|
||||
<stringProp name="HTTPSampler.method">POST</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<boolProp name="HTTPSampler.monitor">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
|
|
Loading…
Reference in a new issue