Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
ad8ab66522
@ -16,4 +16,5 @@ This module contains articles about core Spring functionality
|
|||||||
- [Spring Null-Safety Annotations](https://www.baeldung.com/spring-null-safety-annotations)
|
- [Spring Null-Safety Annotations](https://www.baeldung.com/spring-null-safety-annotations)
|
||||||
- [Using @Autowired in Abstract Classes](https://www.baeldung.com/spring-autowired-abstract-class)
|
- [Using @Autowired in Abstract Classes](https://www.baeldung.com/spring-autowired-abstract-class)
|
||||||
- [Guide to the Spring BeanFactory](https://www.baeldung.com/spring-beanfactory)
|
- [Guide to the Spring BeanFactory](https://www.baeldung.com/spring-beanfactory)
|
||||||
- More articles: [[<-- prev]](/spring-core)
|
- [Read HttpServletRequest Multiple Times](https://www.baeldung.com/spring-reading-httpservletrequest-multiple-times)
|
||||||
|
- More articles: [[<-- prev]](/spring-core)
|
@ -0,0 +1,37 @@
|
|||||||
|
package org.baeldung.cachedrequest;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
|
||||||
|
import javax.servlet.ServletInputStream;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletRequestWrapper;
|
||||||
|
|
||||||
|
import org.springframework.util.StreamUtils;
|
||||||
|
|
||||||
|
public class CachedBodyHttpServletRequest extends HttpServletRequestWrapper {
|
||||||
|
|
||||||
|
private byte[] cachedBody;
|
||||||
|
|
||||||
|
public CachedBodyHttpServletRequest(HttpServletRequest request) throws IOException {
|
||||||
|
super(request);
|
||||||
|
InputStream requestInputStream = request.getInputStream();
|
||||||
|
this.cachedBody = StreamUtils.copyToByteArray(requestInputStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ServletInputStream getInputStream() throws IOException {
|
||||||
|
return new CachedBodyServletInputStream(this.cachedBody);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BufferedReader getReader() throws IOException {
|
||||||
|
// Create a reader from cachedContent
|
||||||
|
// and return it
|
||||||
|
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(this.cachedBody);
|
||||||
|
return new BufferedReader(new InputStreamReader(byteArrayInputStream));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
package org.baeldung.cachedrequest;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import javax.servlet.ReadListener;
|
||||||
|
import javax.servlet.ServletInputStream;
|
||||||
|
|
||||||
|
public class CachedBodyServletInputStream extends ServletInputStream {
|
||||||
|
|
||||||
|
private InputStream cachedBodyInputStream;
|
||||||
|
|
||||||
|
public CachedBodyServletInputStream(byte[] cachedBody) {
|
||||||
|
this.cachedBodyInputStream = new ByteArrayInputStream(cachedBody);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isFinished() {
|
||||||
|
try {
|
||||||
|
return cachedBodyInputStream.available() == 0;
|
||||||
|
} catch (IOException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isReady() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setReadListener(ReadListener readListener) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read() throws IOException {
|
||||||
|
return cachedBodyInputStream.read();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package org.baeldung.cachedrequest;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.servlet.FilterChain;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.annotation.WebFilter;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.springframework.core.Ordered;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
|
@Order(value = Ordered.HIGHEST_PRECEDENCE)
|
||||||
|
@Component
|
||||||
|
@WebFilter(filterName = "ContentCachingFilter", urlPatterns = "/*")
|
||||||
|
public class ContentCachingFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
|
||||||
|
System.out.println("IN ContentCachingFilter ");
|
||||||
|
CachedBodyHttpServletRequest cachedBodyHttpServletRequest = new CachedBodyHttpServletRequest(httpServletRequest);
|
||||||
|
filterChain.doFilter(cachedBodyHttpServletRequest, httpServletResponse);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package org.baeldung.cachedrequest;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
/**
|
||||||
|
* To initialize the WebApplication, Please see
|
||||||
|
* {@link org.baeldung.spring.config.MainWebAppInitializer}
|
||||||
|
*/
|
||||||
|
|
||||||
|
@EnableWebMvc
|
||||||
|
@Configuration
|
||||||
|
@ComponentScan(basePackages = "org.baeldung.cachedrequest")
|
||||||
|
public class HttpRequestDemoConfig implements WebMvcConfigurer {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
package org.baeldung.cachedrequest;
|
||||||
|
|
||||||
|
public class Person {
|
||||||
|
private String firstName;
|
||||||
|
|
||||||
|
private String lastName;
|
||||||
|
|
||||||
|
private int age;
|
||||||
|
|
||||||
|
public Person() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Person(String firstName, String lastName, int age) {
|
||||||
|
this.firstName = firstName;
|
||||||
|
this.lastName = lastName;
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFirstName() {
|
||||||
|
return firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFirstName(String firstName) {
|
||||||
|
this.firstName = firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastName() {
|
||||||
|
return lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastName(String lastName) {
|
||||||
|
this.lastName = lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAge() {
|
||||||
|
return age;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAge(int age) {
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Person{" + "firstName='" + firstName + '\'' + ", lastName='" + lastName + '\'' + ", age=" + age + '}';
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package org.baeldung.cachedrequest;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
public class PersonController {
|
||||||
|
|
||||||
|
@PostMapping(value = "/person")
|
||||||
|
@ResponseStatus(value = HttpStatus.NO_CONTENT)
|
||||||
|
public void printPerson(@RequestBody Person person) {
|
||||||
|
|
||||||
|
System.out.println("In Demo Controller. Person " + "is : " + person);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping(value = "/person")
|
||||||
|
@ResponseStatus(value = HttpStatus.NO_CONTENT)
|
||||||
|
public void getPerson() {
|
||||||
|
|
||||||
|
System.out.println("In Demo Controller get method.");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package org.baeldung.cachedrequest;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import javax.servlet.FilterChain;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.annotation.WebFilter;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.springframework.core.Ordered;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StreamUtils;
|
||||||
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
|
@Order(Ordered.LOWEST_PRECEDENCE)
|
||||||
|
@Component
|
||||||
|
@WebFilter(filterName = "printRequestContentFilter", urlPatterns = "/*")
|
||||||
|
public class PrintRequestContentFilter extends OncePerRequestFilter {
|
||||||
|
@Override
|
||||||
|
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
|
||||||
|
System.out.println("IN PrintRequestContentFilter ");
|
||||||
|
InputStream inputStream = httpServletRequest.getInputStream();
|
||||||
|
byte[] body = StreamUtils.copyToByteArray(inputStream);
|
||||||
|
System.out.println("In PrintRequestContentFilter. Request body is: " + new String(body));
|
||||||
|
filterChain.doFilter(httpServletRequest, httpServletResponse);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package org.baeldung.cachedrequest;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
|
import org.springframework.util.StreamUtils;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class CachedBodyHttpServletRequestUnitTest extends TestCase {
|
||||||
|
|
||||||
|
private CachedBodyServletInputStream servletInputStream;
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void cleanUp() throws IOException {
|
||||||
|
if (null != servletInputStream) {
|
||||||
|
servletInputStream.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGivenHttpServletRequestWithBody_whenCalledGetInputStream_ThenGetsServletInputStreamWithSameBody() throws IOException {
|
||||||
|
// Given
|
||||||
|
byte[] cachedBody = "{\"firstName\" :\"abc\",\"lastName\" : \"xyz\",\"age\" : 30\"}".getBytes();
|
||||||
|
MockHttpServletRequest mockeddHttpServletRequest = new MockHttpServletRequest();
|
||||||
|
mockeddHttpServletRequest.setContent(cachedBody);
|
||||||
|
CachedBodyHttpServletRequest request = new CachedBodyHttpServletRequest(mockeddHttpServletRequest);
|
||||||
|
|
||||||
|
// when
|
||||||
|
InputStream inputStream = request.getInputStream();
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertEquals(new String(cachedBody), new String(StreamUtils.copyToByteArray(inputStream)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGivenHttpServletRequestWithBody_whenCalledGetReader_ThenGetBufferedReaderWithSameBody() throws IOException {
|
||||||
|
// Given
|
||||||
|
byte[] cachedBody = "{\"firstName\" :\"abc\",\"lastName\" : \"xyz\",\"age\" : 30\"}".getBytes();
|
||||||
|
MockHttpServletRequest mockeddHttpServletRequest = new MockHttpServletRequest();
|
||||||
|
mockeddHttpServletRequest.setContent(cachedBody);
|
||||||
|
CachedBodyHttpServletRequest request = new CachedBodyHttpServletRequest(mockeddHttpServletRequest);
|
||||||
|
|
||||||
|
// when
|
||||||
|
BufferedReader bufferedReader = request.getReader();
|
||||||
|
|
||||||
|
// then
|
||||||
|
String line = "";
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
while ((line = bufferedReader.readLine()) != null) {
|
||||||
|
builder.append(line);
|
||||||
|
}
|
||||||
|
assertEquals(new String(cachedBody), builder.toString());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,98 @@
|
|||||||
|
package org.baeldung.cachedrequest;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.servlet.ReadListener;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
|
import org.springframework.util.StreamUtils;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class CachedBodyServletInputStreamUnitTest extends TestCase {
|
||||||
|
|
||||||
|
private CachedBodyServletInputStream servletInputStream;
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void cleanUp() throws IOException {
|
||||||
|
if (null != servletInputStream) {
|
||||||
|
servletInputStream.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGivenServletInputStreamCreated_whenCalledisFinished_Thenfalse() {
|
||||||
|
// Given
|
||||||
|
byte[] cachedBody = "{\"firstName\" :\"abc\",\"lastName\" : \"xyz\",\"age\" : 30\"}".getBytes();
|
||||||
|
servletInputStream = new CachedBodyServletInputStream(cachedBody);
|
||||||
|
|
||||||
|
// when
|
||||||
|
boolean finished = servletInputStream.isFinished();
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertFalse(finished);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGivenServletInputStreamCreatedAndBodyRead_whenCalledisFinished_ThenTrue() throws IOException {
|
||||||
|
// Given
|
||||||
|
byte[] cachedBody = "{\"firstName\" :\"abc\",\"lastName\" : \"xyz\",\"age\" : 30\"}".getBytes();
|
||||||
|
servletInputStream = new CachedBodyServletInputStream(cachedBody);
|
||||||
|
StreamUtils.copyToByteArray(servletInputStream);
|
||||||
|
|
||||||
|
// when
|
||||||
|
boolean finished = servletInputStream.isFinished();
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertTrue(finished);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGivenServletInputStreamCreatedAndBodyRead_whenCalledIsReady_ThenTrue() throws IOException {
|
||||||
|
// Given
|
||||||
|
byte[] cachedBody = "{\"firstName\" :\"abc\",\"lastName\" : \"xyz\",\"age\" : 30\"}".getBytes();
|
||||||
|
servletInputStream = new CachedBodyServletInputStream(cachedBody);
|
||||||
|
|
||||||
|
// when
|
||||||
|
boolean ready = servletInputStream.isReady();
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertTrue(ready);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGivenServletInputStreamCreated_whenCalledIsRead_ThenReturnsBody() throws IOException {
|
||||||
|
// Given
|
||||||
|
byte[] cachedBody = "{\"firstName\" :\"abc\",\"lastName\" : \"xyz\",\"age\" : 30\"}".getBytes();
|
||||||
|
servletInputStream = new CachedBodyServletInputStream(cachedBody);
|
||||||
|
|
||||||
|
// when
|
||||||
|
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||||
|
int len = 0;
|
||||||
|
byte[] buffer = new byte[1024];
|
||||||
|
while ((len = servletInputStream.read(buffer)) != -1) {
|
||||||
|
byteArrayOutputStream.write(buffer, 0, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertEquals(new String(cachedBody), new String(byteArrayOutputStream.toByteArray()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = UnsupportedOperationException.class)
|
||||||
|
public void testGivenServletInputStreamCreated_whenCalledIsRead_ThenThrowsException() throws IOException {
|
||||||
|
// Given
|
||||||
|
byte[] cachedBody = "{\"firstName\" :\"abc\",\"lastName\" : \"xyz\",\"age\" : 30\"}".getBytes();
|
||||||
|
servletInputStream = new CachedBodyServletInputStream(cachedBody);
|
||||||
|
|
||||||
|
// when
|
||||||
|
servletInputStream.setReadListener(Mockito.mock(ReadListener.class));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
package org.baeldung.cachedrequest;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.servlet.FilterChain;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.InjectMocks;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
|
import org.springframework.mock.web.MockHttpServletResponse;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class ContentCachingFilterUnitTest extends TestCase {
|
||||||
|
|
||||||
|
@InjectMocks
|
||||||
|
private ContentCachingFilter filterToTest;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGivenHttpRequest_WhenDoFilter_thenCreatesRequestWrapperObject() throws IOException, ServletException {
|
||||||
|
// Given
|
||||||
|
MockHttpServletRequest mockedRequest = new MockHttpServletRequest();
|
||||||
|
MockHttpServletResponse mockedResponse = new MockHttpServletResponse();
|
||||||
|
FilterChain mockedFilterChain = Mockito.mock(FilterChain.class);
|
||||||
|
|
||||||
|
// when
|
||||||
|
filterToTest.doFilter(mockedRequest, mockedResponse, mockedFilterChain);
|
||||||
|
|
||||||
|
// then
|
||||||
|
Mockito.verify(mockedFilterChain, Mockito.times(1))
|
||||||
|
.doFilter(Mockito.any(CachedBodyHttpServletRequest.class), Mockito.any(MockHttpServletResponse.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package org.baeldung.cachedrequest;
|
||||||
|
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.print.attribute.PrintRequestAttribute;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
import org.springframework.test.web.servlet.ResultActions;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
|
@RunWith(SpringRunner.class)
|
||||||
|
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = { HttpRequestDemoConfig.class, ContentCachingFilter.class, PrintRequestAttribute.class })
|
||||||
|
@AutoConfigureMockMvc
|
||||||
|
public class PersonControllerIntegrationTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MockMvc mockMvc;
|
||||||
|
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenValidInput_thenCreateBook() throws IOException, Exception {
|
||||||
|
// assign - given
|
||||||
|
Person book = new Person("sumit", "abc", 100);
|
||||||
|
|
||||||
|
// act - when
|
||||||
|
ResultActions result = mockMvc.perform(post("/person").accept(MediaType.APPLICATION_JSON)
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.content(objectMapper.writeValueAsString(book)));
|
||||||
|
|
||||||
|
// assert - then
|
||||||
|
result.andExpect(status().isNoContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package org.baeldung.cachedrequest;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.servlet.FilterChain;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.InjectMocks;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
|
import org.springframework.mock.web.MockHttpServletResponse;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class PrintRequestContentFilterUnitTest extends TestCase {
|
||||||
|
|
||||||
|
@InjectMocks
|
||||||
|
private PrintRequestContentFilter filterToTest;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGivenHttpRequest_WhenDoFilter_thenReadsBody() throws IOException, ServletException {
|
||||||
|
// Given
|
||||||
|
MockHttpServletRequest mockedRequest = new MockHttpServletRequest();
|
||||||
|
MockHttpServletResponse mockedResponse = new MockHttpServletResponse();
|
||||||
|
FilterChain mockedFilterChain = Mockito.mock(FilterChain.class);
|
||||||
|
CachedBodyHttpServletRequest cachedBodyHttpServletRequest = new CachedBodyHttpServletRequest(mockedRequest);
|
||||||
|
|
||||||
|
// when
|
||||||
|
filterToTest.doFilter(cachedBodyHttpServletRequest, mockedResponse, mockedFilterChain);
|
||||||
|
|
||||||
|
// then
|
||||||
|
Mockito.verify(mockedFilterChain, Mockito.times(1))
|
||||||
|
.doFilter(cachedBodyHttpServletRequest, mockedResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
20
testing-modules/gatling/Jenkinsfile
vendored
Normal file
20
testing-modules/gatling/Jenkinsfile
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
pipeline {
|
||||||
|
agent any
|
||||||
|
stages {
|
||||||
|
stage("Build Maven") {
|
||||||
|
steps {
|
||||||
|
sh 'mvn -B clean package'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage("Run Gatling") {
|
||||||
|
steps {
|
||||||
|
sh 'mvn gatling:test'
|
||||||
|
}
|
||||||
|
post {
|
||||||
|
always {
|
||||||
|
gatlingArchive()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +1,13 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>org.baeldung</groupId>
|
<groupId>org.baeldung</groupId>
|
||||||
<artifactId>gatling</artifactId>
|
<artifactId>gatling</artifactId>
|
||||||
<version>1.0-SNAPSHOT</version>
|
<version>1.0-SNAPSHOT</version>
|
||||||
<name>gatling</name>
|
<name>gatling</name>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
@ -15,122 +15,106 @@
|
|||||||
<relativePath>../../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencyManagement>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.gatling</groupId>
|
|
||||||
<artifactId>gatling-app</artifactId>
|
|
||||||
<version>${gatling.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.gatling</groupId>
|
|
||||||
<artifactId>gatling-recorder</artifactId>
|
|
||||||
<version>${gatling.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.gatling.highcharts</groupId>
|
|
||||||
<artifactId>gatling-charts-highcharts</artifactId>
|
|
||||||
<version>${gatling.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.scala-lang</groupId>
|
|
||||||
<artifactId>scala-library</artifactId>
|
|
||||||
<version>${scala.version}</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
</dependencyManagement>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.gatling.highcharts</groupId>
|
|
||||||
<artifactId>gatling-charts-highcharts</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.gatling</groupId>
|
|
||||||
<artifactId>gatling-app</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.gatling</groupId>
|
|
||||||
<artifactId>gatling-recorder</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.scala-lang</groupId>
|
|
||||||
<artifactId>scala-library</artifactId>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
<dependencyManagement>
|
||||||
<testSourceDirectory>src/test/scala</testSourceDirectory>
|
<dependencies>
|
||||||
<pluginManagement>
|
<dependency>
|
||||||
<plugins>
|
<groupId>io.gatling</groupId>
|
||||||
<plugin>
|
<artifactId>gatling-app</artifactId>
|
||||||
<groupId>net.alchim31.maven</groupId>
|
<version>${gatling.version}</version>
|
||||||
<artifactId>scala-maven-plugin</artifactId>
|
</dependency>
|
||||||
<version>${scala-maven-plugin.version}</version>
|
<dependency>
|
||||||
</plugin>
|
<groupId>io.gatling</groupId>
|
||||||
</plugins>
|
<artifactId>gatling-recorder</artifactId>
|
||||||
</pluginManagement>
|
<version>${gatling.version}</version>
|
||||||
<plugins>
|
</dependency>
|
||||||
<plugin>
|
<dependency>
|
||||||
<groupId>net.alchim31.maven</groupId>
|
<groupId>io.gatling.highcharts</groupId>
|
||||||
<artifactId>scala-maven-plugin</artifactId>
|
<artifactId>gatling-charts-highcharts</artifactId>
|
||||||
<executions>
|
<version>${gatling.version}</version>
|
||||||
<execution>
|
</dependency>
|
||||||
<goals>
|
<dependency>
|
||||||
<goal>testCompile</goal>
|
<groupId>org.scala-lang</groupId>
|
||||||
</goals>
|
<artifactId>scala-library</artifactId>
|
||||||
<configuration>
|
<version>${scala.version}</version>
|
||||||
<args>
|
</dependency>
|
||||||
<!--<arg>-Ybackend:GenBCode</arg> -->
|
</dependencies>
|
||||||
<arg>-Ydelambdafy:method</arg>
|
</dependencyManagement>
|
||||||
<arg>-target:jvm-1.8</arg>
|
|
||||||
<arg>-deprecation</arg>
|
|
||||||
<arg>-feature</arg>
|
|
||||||
<arg>-unchecked</arg>
|
|
||||||
<arg>-language:implicitConversions</arg>
|
|
||||||
<arg>-language:postfixOps</arg>
|
|
||||||
</args>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
<profiles>
|
|
||||||
<profile>
|
|
||||||
<id>simulation</id>
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>io.gatling</groupId>
|
|
||||||
<artifactId>gatling-maven-plugin</artifactId>
|
|
||||||
<version>${gatling-maven-plugin.version}</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<phase>test</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>execute</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<disableCompiler>true</disableCompiler>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</profile>
|
|
||||||
</profiles>
|
|
||||||
|
|
||||||
<properties>
|
<dependencies>
|
||||||
<maven.compiler.source>1.8</maven.compiler.source>
|
<dependency>
|
||||||
<maven.compiler.target>1.8</maven.compiler.target>
|
<groupId>io.gatling.highcharts</groupId>
|
||||||
<encoding>UTF-8</encoding>
|
<artifactId>gatling-charts-highcharts</artifactId>
|
||||||
<scala.version>2.12.6</scala.version> <!--2.11.12 --> <!--2.12.6 -->
|
</dependency>
|
||||||
<gatling.version>2.3.1</gatling.version> <!--2.2.5 --> <!--2.3.1 -->
|
<dependency>
|
||||||
<scala-maven-plugin.version>3.2.2</scala-maven-plugin.version> <!--3.2.2 --> <!--3.3.2 -->
|
<groupId>io.gatling</groupId>
|
||||||
<gatling-maven-plugin.version>2.2.4</gatling-maven-plugin.version> <!--2.2.1 --> <!--2.2.4 -->
|
<artifactId>gatling-app</artifactId>
|
||||||
</properties>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.gatling</groupId>
|
||||||
|
<artifactId>gatling-recorder</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.scala-lang</groupId>
|
||||||
|
<artifactId>scala-library</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<testSourceDirectory>src/test/scala</testSourceDirectory>
|
||||||
|
<pluginManagement>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>net.alchim31.maven</groupId>
|
||||||
|
<artifactId>scala-maven-plugin</artifactId>
|
||||||
|
<version>${scala-maven-plugin.version}</version>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</pluginManagement>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>net.alchim31.maven</groupId>
|
||||||
|
<artifactId>scala-maven-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>testCompile</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<args>
|
||||||
|
<!--<arg>-Ybackend:GenBCode</arg> -->
|
||||||
|
<arg>-Ydelambdafy:method</arg>
|
||||||
|
<arg>-target:jvm-1.8</arg>
|
||||||
|
<arg>-deprecation</arg>
|
||||||
|
<arg>-feature</arg>
|
||||||
|
<arg>-unchecked</arg>
|
||||||
|
<arg>-language:implicitConversions</arg>
|
||||||
|
<arg>-language:postfixOps</arg>
|
||||||
|
</args>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>io.gatling</groupId>
|
||||||
|
<artifactId>gatling-maven-plugin</artifactId>
|
||||||
|
<version>${gatling-maven-plugin.version}</version>
|
||||||
|
<configuration>
|
||||||
|
<simulationClass>org.baeldung.RecordedSimulation</simulationClass>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
|
<encoding>UTF-8</encoding>
|
||||||
|
<scala.version>2.12.6</scala.version> <!--2.11.12 --> <!--2.12.6 -->
|
||||||
|
<gatling.version>3.3.1</gatling.version> <!--2.2.5 --> <!--2.3.1 -->
|
||||||
|
<scala-maven-plugin.version>4.3.0</scala-maven-plugin.version> <!--3.2.2 --> <!--3.3.2 -->
|
||||||
|
<gatling-maven-plugin.version>3.0.4</gatling-maven-plugin.version> <!--2.2.1 --> <!--2.2.4 -->
|
||||||
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@ -3,11 +3,10 @@ import io.gatling.core.config.GatlingPropertiesBuilder
|
|||||||
|
|
||||||
object Engine extends App {
|
object Engine extends App {
|
||||||
|
|
||||||
val props = new GatlingPropertiesBuilder
|
val props = new GatlingPropertiesBuilder()
|
||||||
props.dataDirectory(IDEPathHelper.dataDirectory.toString)
|
.resourcesDirectory(IDEPathHelper.resourcesDirectory.toString)
|
||||||
props.resultsDirectory(IDEPathHelper.resultsDirectory.toString)
|
.resultsDirectory(IDEPathHelper.resultsDirectory.toString)
|
||||||
props.bodiesDirectory(IDEPathHelper.bodiesDirectory.toString)
|
.binariesDirectory(IDEPathHelper.mavenBinariesDirectory.toString)
|
||||||
props.binariesDirectory(IDEPathHelper.mavenBinariesDirectory.toString)
|
|
||||||
|
|
||||||
Gatling.fromMap(props.build)
|
Gatling.fromMap(props.build)
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import io.gatling.commons.util.PathHelper._
|
|||||||
|
|
||||||
object IDEPathHelper {
|
object IDEPathHelper {
|
||||||
|
|
||||||
val gatlingConfUrl: Path = getClass.getClassLoader.getResource("gatling.conf").toURI
|
val gatlingConfUrl: Path = getClass.getClassLoader.getResource("gatling.conf")
|
||||||
val projectRootDir = gatlingConfUrl.ancestor(3)
|
val projectRootDir = gatlingConfUrl.ancestor(3)
|
||||||
|
|
||||||
val mavenSourcesDirectory = projectRootDir / "src" / "test" / "scala"
|
val mavenSourcesDirectory = projectRootDir / "src" / "test" / "scala"
|
||||||
@ -12,11 +12,8 @@ object IDEPathHelper {
|
|||||||
val mavenTargetDirectory = projectRootDir / "target"
|
val mavenTargetDirectory = projectRootDir / "target"
|
||||||
val mavenBinariesDirectory = mavenTargetDirectory / "test-classes"
|
val mavenBinariesDirectory = mavenTargetDirectory / "test-classes"
|
||||||
|
|
||||||
val dataDirectory = mavenResourcesDirectory / "data"
|
val resourcesDirectory = mavenResourcesDirectory
|
||||||
val bodiesDirectory = mavenResourcesDirectory / "bodies"
|
val recorderSimulationsDirectory = mavenSourcesDirectory
|
||||||
|
|
||||||
val recorderOutputDirectory = mavenSourcesDirectory
|
|
||||||
val resultsDirectory = mavenTargetDirectory / "gatling"
|
val resultsDirectory = mavenTargetDirectory / "gatling"
|
||||||
|
|
||||||
val recorderConfigFile = mavenResourcesDirectory / "recorder.conf"
|
val recorderConfigFile = mavenResourcesDirectory / "recorder.conf"
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,10 @@ import io.gatling.recorder.config.RecorderPropertiesBuilder
|
|||||||
|
|
||||||
object Recorder extends App {
|
object Recorder extends App {
|
||||||
|
|
||||||
val props = new RecorderPropertiesBuilder
|
val props = new RecorderPropertiesBuilder()
|
||||||
props.simulationOutputFolder(IDEPathHelper.recorderOutputDirectory.toString)
|
.simulationsFolder(IDEPathHelper.recorderSimulationsDirectory.toString)
|
||||||
props.simulationPackage("org.baeldung")
|
.simulationPackage("org.baeldung")
|
||||||
props.bodiesFolder(IDEPathHelper.bodiesDirectory.toString)
|
.resourcesFolder(IDEPathHelper.resourcesDirectory.toString)
|
||||||
|
|
||||||
GatlingRecorder.fromMap(props.build, Some(IDEPathHelper.recorderConfigFile))
|
GatlingRecorder.fromMap(props.build, Some(IDEPathHelper.recorderConfigFile))
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ import io.gatling.jdbc.Predef._
|
|||||||
class RecordedSimulation extends Simulation {
|
class RecordedSimulation extends Simulation {
|
||||||
|
|
||||||
val httpProtocol = http
|
val httpProtocol = http
|
||||||
.baseURL("http://computer-database.gatling.io")
|
.baseUrl("http://computer-database.gatling.io")
|
||||||
.inferHtmlResources(BlackList(""".*\.css""", """.*\.js""", """.*\.ico"""), WhiteList())
|
.inferHtmlResources(BlackList(""".*\.css""", """.*\.js""", """.*\.ico"""), WhiteList())
|
||||||
.acceptHeader("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
|
.acceptHeader("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
|
||||||
.acceptEncodingHeader("gzip, deflate")
|
.acceptEncodingHeader("gzip, deflate")
|
||||||
|
@ -0,0 +1,102 @@
|
|||||||
|
package com.baeldung.mockito.fluentapi;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Pizza {
|
||||||
|
|
||||||
|
public enum PizzaSize {
|
||||||
|
LARGE, MEDIUM, SMALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private PizzaSize size;
|
||||||
|
private List<String> toppings;
|
||||||
|
private boolean stuffedCrust;
|
||||||
|
private boolean collect;
|
||||||
|
private Integer discount;
|
||||||
|
|
||||||
|
private Pizza(PizzaBuilder builder) {
|
||||||
|
this.name = builder.name;
|
||||||
|
this.size = builder.size;
|
||||||
|
this.toppings = builder.toppings;
|
||||||
|
this.stuffedCrust = builder.stuffedCrust;
|
||||||
|
this.collect = builder.collect;
|
||||||
|
this.discount = builder.discount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PizzaSize getSize() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getToppings() {
|
||||||
|
return toppings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isStuffedCrust() {
|
||||||
|
return stuffedCrust;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCollecting() {
|
||||||
|
return collect;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getDiscount() {
|
||||||
|
return discount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PizzaBuilder {
|
||||||
|
private String name;
|
||||||
|
private PizzaSize size;
|
||||||
|
|
||||||
|
private List<String> toppings;
|
||||||
|
private boolean stuffedCrust;
|
||||||
|
private boolean collect;
|
||||||
|
private Integer discount = null;
|
||||||
|
|
||||||
|
public PizzaBuilder() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public PizzaBuilder name(String name) {
|
||||||
|
this.name = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PizzaBuilder size(PizzaSize size) {
|
||||||
|
this.size = size;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PizzaBuilder withExtraTopping(String extraTopping) {
|
||||||
|
if (this.toppings == null) {
|
||||||
|
toppings = new ArrayList<>();
|
||||||
|
}
|
||||||
|
this.toppings.add(extraTopping);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PizzaBuilder withStuffedCrust(boolean stuffedCrust) {
|
||||||
|
this.stuffedCrust = stuffedCrust;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PizzaBuilder willCollect(boolean collect) {
|
||||||
|
this.collect = collect;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PizzaBuilder applyDiscount(Integer discount) {
|
||||||
|
this.discount = discount;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pizza build() {
|
||||||
|
return new Pizza(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package com.baeldung.mockito.fluentapi;
|
||||||
|
|
||||||
|
import com.baeldung.mockito.fluentapi.Pizza.PizzaSize;
|
||||||
|
|
||||||
|
public class PizzaService {
|
||||||
|
|
||||||
|
private Pizza.PizzaBuilder builder;
|
||||||
|
|
||||||
|
public PizzaService(Pizza.PizzaBuilder builder) {
|
||||||
|
this.builder = builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pizza orderHouseSpecial() {
|
||||||
|
return builder.name("Special")
|
||||||
|
.size(PizzaSize.LARGE)
|
||||||
|
.withExtraTopping("Mushrooms")
|
||||||
|
.withStuffedCrust(true)
|
||||||
|
.withExtraTopping("Chilli")
|
||||||
|
.willCollect(true)
|
||||||
|
.applyDiscount(20)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,88 @@
|
|||||||
|
package com.baeldung.mockito.fluentapi;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mockito.Answers;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.mockito.Captor;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
import com.baeldung.mockito.fluentapi.Pizza.PizzaBuilder;
|
||||||
|
import com.baeldung.mockito.fluentapi.Pizza.PizzaSize;
|
||||||
|
|
||||||
|
public class PizzaServiceUnitTest {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private Pizza expectedPizza;
|
||||||
|
|
||||||
|
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||||
|
private PizzaBuilder anotherbuilder;
|
||||||
|
|
||||||
|
@Captor
|
||||||
|
private ArgumentCaptor<String> stringCaptor;
|
||||||
|
@Captor
|
||||||
|
private ArgumentCaptor<Pizza.PizzaSize> sizeCaptor;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenTraditonalMocking_whenServiceInvoked_thenPizzaIsBuilt() {
|
||||||
|
PizzaBuilder nameBuilder = Mockito.mock(Pizza.PizzaBuilder.class);
|
||||||
|
PizzaBuilder sizeBuilder = Mockito.mock(Pizza.PizzaBuilder.class);
|
||||||
|
PizzaBuilder firstToppingBuilder = Mockito.mock(Pizza.PizzaBuilder.class);
|
||||||
|
PizzaBuilder secondToppingBuilder = Mockito.mock(Pizza.PizzaBuilder.class);
|
||||||
|
PizzaBuilder stuffedBuilder = Mockito.mock(Pizza.PizzaBuilder.class);
|
||||||
|
PizzaBuilder willCollectBuilder = Mockito.mock(Pizza.PizzaBuilder.class);
|
||||||
|
PizzaBuilder discountBuilder = Mockito.mock(Pizza.PizzaBuilder.class);
|
||||||
|
|
||||||
|
PizzaBuilder builder = Mockito.mock(Pizza.PizzaBuilder.class);
|
||||||
|
when(builder.name(anyString())).thenReturn(nameBuilder);
|
||||||
|
when(nameBuilder.size(any(Pizza.PizzaSize.class))).thenReturn(sizeBuilder);
|
||||||
|
when(sizeBuilder.withExtraTopping(anyString())).thenReturn(firstToppingBuilder);
|
||||||
|
when(firstToppingBuilder.withStuffedCrust(anyBoolean())).thenReturn(stuffedBuilder);
|
||||||
|
when(stuffedBuilder.withExtraTopping(anyString())).thenReturn(secondToppingBuilder);
|
||||||
|
when(secondToppingBuilder.willCollect(anyBoolean())).thenReturn(willCollectBuilder);
|
||||||
|
when(willCollectBuilder.applyDiscount(anyInt())).thenReturn(discountBuilder);
|
||||||
|
when(discountBuilder.build()).thenReturn(expectedPizza);
|
||||||
|
|
||||||
|
PizzaService service = new PizzaService(builder);
|
||||||
|
assertEquals("Expected Pizza", expectedPizza, service.orderHouseSpecial());
|
||||||
|
|
||||||
|
verify(builder).name(stringCaptor.capture());
|
||||||
|
assertEquals("Pizza name: ", "Special", stringCaptor.getValue());
|
||||||
|
|
||||||
|
verify(nameBuilder).size(sizeCaptor.capture());
|
||||||
|
assertEquals("Pizza size: ", PizzaSize.LARGE, sizeCaptor.getValue());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenDeepStubs_whenServiceInvoked_thenPizzaIsBuilt() {
|
||||||
|
Mockito.when(anotherbuilder.name(anyString())
|
||||||
|
.size(any(Pizza.PizzaSize.class))
|
||||||
|
.withExtraTopping(anyString())
|
||||||
|
.withStuffedCrust(anyBoolean())
|
||||||
|
.withExtraTopping(anyString())
|
||||||
|
.willCollect(anyBoolean())
|
||||||
|
.applyDiscount(anyInt())
|
||||||
|
.build())
|
||||||
|
.thenReturn(expectedPizza);
|
||||||
|
|
||||||
|
PizzaService service = new PizzaService(anotherbuilder);
|
||||||
|
assertEquals("Expected Pizza", expectedPizza, service.orderHouseSpecial());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package com.baeldung.mockito.fluentapi;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.baeldung.mockito.fluentapi.Pizza.PizzaSize;
|
||||||
|
|
||||||
|
public class PizzaUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenFluentPizzaApi_whenBuilt_thenPizzaHasCorrectAttributes() {
|
||||||
|
Pizza pizza = new Pizza.PizzaBuilder()
|
||||||
|
.name("Margherita")
|
||||||
|
.size(PizzaSize.LARGE)
|
||||||
|
.withExtraTopping("Mushroom")
|
||||||
|
.withStuffedCrust(false)
|
||||||
|
.willCollect(true)
|
||||||
|
.applyDiscount(20)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assertEquals("Pizza name: ", "Margherita", pizza.getName());
|
||||||
|
assertEquals("Pizza size: ", PizzaSize.LARGE, pizza.getSize());
|
||||||
|
assertEquals("Extra toppings: ", "Mushroom", pizza.getToppings()
|
||||||
|
.get(0));
|
||||||
|
assertFalse("Has stuffed crust: ", pizza.isStuffedCrust());
|
||||||
|
assertTrue("Will collect: ", pizza.isCollecting());
|
||||||
|
assertEquals("Discounts: ", Integer.valueOf(20), pizza.getDiscount());
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user