当我的控制器具有异步servlet性质时,如何在MockMvc中验证/测试500内部服务器错误?
我正在为我的REST端点编写单元测试用例作为测试用例的一部分我需要验证服务器发送500内部错误作为http代码并带有相应的错误消息.
这是我的基于春季启动的应用程序:(为了更好的可读性,省略了所有导入)
@RestController
@RequestMapping("/user")
@EnableAutoConfiguration
@SpringBootApplication
public class App
{
@RequestMapping(method = RequestMethod.GET, value = "/{name}",
produces = MediaType.APPLICATION_JSON_VALUE)
private DeferredResult<String> greetByJson(@PathVariable("name") final String name){
DeferredResult<String> dResult = new DeferredResult<String>();
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(5000);
dResult.setErrorResult(new RuntimeException("Boom!!! time for Internal server error"));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
return dResult;
}
public static void main( String[] args )
{
SpringApplication.run(App.class);
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的MovkMvc JUnit测试用例:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = …Run Code Online (Sandbox Code Playgroud) 我正在为带有 spting boot 的控制器编写一个单元@WebMvcTest。
使用@WebMvcTest,我将能够注入一个MockMvc对象,如下所示:-
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {TestConfig.class})
@WebMvcTest
class MyControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
public void my_controller_test() throws Exception {
mockMvc.perform(post("/create-user"))
.andExpect(status().isCreated());
}
}
Run Code Online (Sandbox Code Playgroud)
在控制器中,我Principal使用 spring 注入一个参数HandlerMethodArgumentResolver。请告诉我如何使用 编写单元测试MockMvc,以便我可以注入模拟Principal对象作为控制器方法中的参数。
自动配置的 Spring MVC 测试部分解释了带有注释的测试@WebMvcTest将扫描HandlerMethodArgumentResolver. 所以我创建了一个 bean,它扩展HandlerMethodArgumentResolver并返回模拟Principal对象,如下所示。
@Component
public class MockPrincipalArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterType().equals(Principal.class);
}
@Override
public Object …Run Code Online (Sandbox Code Playgroud) 我有一个控制器,它响应一个调用返回XML数据.下面是代码
@RequestMapping(value = "/balance.xml",method = RequestMethod.GET,produces="application/xml")
public AccountBalanceList getAccountBalanceList(@RequestParam("accountId") Integer accountId)
{
AccountBalanceList accountBalanceList = new AccountBalanceList();
List<AccountBalance> list = new ArrayList<AccountBalance>();
list = accountService.getAccountBalanceList(accountId);
accountBalanceList.setList(list);
return accountBalanceList;
}
Run Code Online (Sandbox Code Playgroud)
accountBalanceList用xml注释.我从这个调用得到的响应是这样的
<points>
<point>
<balance>$1134.99</balance>
<lots>10000.0</lots>
<onDate>2012-11-11 15:44:00</onDate>
</point>
</points>
Run Code Online (Sandbox Code Playgroud)
我想为这个控制器调用编写集成测试.我知道如何使用JSON响应测试控制器,但我不知道如何测试响应是否在XML中.任何帮助将不胜感激.
问候
model-view-controller integration-testing spring-mvc spring-mvc-test
测试一个spring文件上传表单,controlelr签名看起来像这样
@RequestMapping(value = "upload", method = RequestMethod.POST)
@ResponseBody
public void upload(@RequestParam("file") MultipartFile multipartFile) {}
Run Code Online (Sandbox Code Playgroud)
并测试这个
final MockMultipartFile file
= new MockMultipartFile("content", "myFile.txt", "text/plain", "hello".getBytes());
MockHttpServletRequestBuilder mockHttpServletRequestBuilder =
.fileUpload("/upload/")
.file(file)
.accept(MediaType.APPLICATION_JSON);
Run Code Online (Sandbox Code Playgroud)
但我得到上述内容:错误消息=必需的MultipartFile参数'file'不存在
登录jsp表单和spring security xml配置如下:
<spring:url value="/j_spring_security_check" var="login" />
<form action="${login}" method="POST">
<fieldset>
<legend>Login</legend>
<input type="text" name="j_username" id="username" placeholder="Usename"/>
<input type="text" name="j_password" id="password" placeholder="Password"/>
<input type="submit" value="Login" />
</fieldset>
</form>
...
<security:form-login login-page="/public/authentication/login.htm"
login-processing-url="/j_spring_security_check"
default-target-url="/public/index.htm"
authentication-failure-url="/public/authentication/login.htm?authenticationNok=1"/>
Run Code Online (Sandbox Code Playgroud)
这是形式总结的测试:
@Test
public void testLoginPostController() throws Exception {
Account account = new AccountBuilder("test", "test", "test@gmail.com", Address.FAKE_EMPTY_ADDRESS4TESTS)
.build();
this.mockMvc.perform(post("/j_spring_security_check").param("j_username", account.getUsername()).param("j_password", "test"))
.andDo(print())
.andExpect(status().isMovedTemporarily())
.andExpect(view().name("redirect:/public/index.htm"));
}
Run Code Online (Sandbox Code Playgroud)
但是我得到了: java.lang.AssertionError: Status expected:<302> but was:<404>
当我在浏览器中打开登录页面时,我看到生成的表单是:
<form action="/SpringMvcExample/j_spring_security_check" method="POST">
Run Code Online (Sandbox Code Playgroud)
好的,我试着改变测试:
this.mockMvc.perform(post("/SpringMvcExample/j_spring_security_check").param("j_username", account.getUsername()).param("j_password", "test"))
Run Code Online (Sandbox Code Playgroud)
但得到了相同的结果.同时,当我在浏览器中提交登录表单时,它会将我重定向到public/index.htm页面,如测试中的exptect.
我究竟做错了什么?
我正在尝试运行此Spring会话示例,但是,我使用Maven而不是Gradle.我在以下情况下得到以下错误:a)运行WAR文件和b)在WildFly8.2服务器中部署WAR
快速搜索表明问题可能是pom.xml中引用的各种依赖项之间存在冲突的版本.
这个错误的根本原因和解决方案是什么?
运行或部署WAR时出错
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:53)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalArgumentException: Cannot instantiate interface org.springframework.boot.SpringApplicationRunListener : org.springframework.boot.context.event.EventPublishingRunListener
at org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:381)
at org.springframework.boot.SpringApplication.getRunListeners(SpringApplication.java:352)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:274)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:952)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:941)
at hello.Application.main(Application.java:25)
... 6 more
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:408)
at org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:377)
... 11 more
Caused by: java.lang.NoSuchFieldError: INSTANCE
at org.springframework.boot.SpringApplication.asUnmodifiableOrderedSet(SpringApplication.java:1031)
at org.springframework.boot.SpringApplication.getListeners(SpringApplication.java:930)
at org.springframework.boot.context.event.EventPublishingRunListener.<init>(EventPublishingRunListener.java:47)
... 16 more
Run Code Online (Sandbox Code Playgroud)
这是我完整的POM.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" …Run Code Online (Sandbox Code Playgroud) 尝试使用MockMvcResultMatchers从Spring REST服务测试JSON输出时遇到问题,其中返回的对象应包含Long值.
只有当JSON对象中的值高于Integer.MAX_VALUE时,测试才会通过.这对我来说有点奇怪,因为我觉得我应该能够测试所有适用的值.
据我所知,由于JSON不包含类型信息,因此它在反序列化时对类型进行了最佳猜测,但我希望在MockMvcResultMatchers中执行比较时,有一种强制提取类型的方法.
完整代码如下,但测试是:
@Test
public void testGetObjectWithLong() throws Exception {
Long id = 45l;
ObjectWithLong objWithLong = new ObjectWithLong(id);
Mockito.when(service.getObjectWithLong(String.valueOf(id))).thenReturn(objWithLong);
mockMvc.perform(MockMvcRequestBuilders.get("/Test/" + id))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$longvalue")
.value(Matchers.isA(Long.class)))
.andExpect(MockMvcResultMatchers.jsonPath("$longvalue")
.value(Matchers.equalTo(id)));
}
Run Code Online (Sandbox Code Playgroud)
结果是:
java.lang.AssertionError: JSON path$longvalue
Expected: is an instance of java.lang.Long
but: <45> is a java.lang.Integer
at org.springframework.test.util.MatcherAssertionErrors.assertThat(MatcherAssertionErrors.java:80)
...
Run Code Online (Sandbox Code Playgroud)
任何关于解决这个问题的正确方法的想法或建议都将受到赞赏.显然,我可以将Integer.MAX_VALUE添加到测试中的id字段,但这看起来很脆弱.
提前致谢.
除第三方库外,以下内容应该是自包含的
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.stereotype.Service;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; …Run Code Online (Sandbox Code Playgroud) 我真的很难转换List<User> users为Page<User>spring数据mongo?注意Page是来自的API org.springframework.data.domain.Page;
我使用的Pagination是Spring Data Mongo,所以我需要发送Page<User>而不是发送List<User>.
如果我不想使用Page<>存储库方法,我们如何从列表中获取页面?
请帮我.
我已经编写了一个测试并且之前成功但现在我得到一个AssertionError:没有JSON Path的值.
@Test
public void testCreate() throws Exception {
Wine wine = new Wine();
wine.setName("Bordeaux");
wine.setCost(BigDecimal.valueOf(10.55));
new Expectations() {
{
wineService.create((WineDTO) any);
result = wine;
}
};
MockMultipartFile jsonFile = new MockMultipartFile("form", "", "application/json", "{\"name\":\"Bordeaux\", \"cost\": \"10.55\"}".getBytes());
this.webClient.perform(MockMvcRequestBuilders.fileUpload("/wine").file(jsonFile))
.andExpect(MockMvcResultMatchers.status().is(200))
.andExpect(MockMvcResultMatchers.jsonPath("$.name").value("Bordeaux"))
.andExpect(MockMvcResultMatchers.jsonPath("$.cost").value(10.55));
}
Run Code Online (Sandbox Code Playgroud)
我得到的错误是:
java.lang.AssertionError: No value for JSON path: $.name, exception: No results path for $['name']
Run Code Online (Sandbox Code Playgroud)
我不明白它没有得到什么或者缺少什么.
我有一个 main@SpringBootApplication需要扫描特定的包才能启用 JPA 存储库,因此我使用@EnableJpaRepositories它来指定它。现在我正在实现单元测试,我只想测试控制器组件,所以我按照官方文档中的教程进行操作,他们使用@WebMvcTest(MyController.class)服务依赖项来测试控制器。问题是这对我不起作用,因为它试图加载我在主 Spring Boot 应用程序中指定的 JpaRepositories (当我@EnableJpaRepositories在主类中注释时,测试运行没有问题)。
我猜我需要为测试类创建一个特定的配置,这样它就可以忽略主要配置(因为我只想加载控制器并模拟服务层),但我不知道如何创建这样的配置。我尝试添加一个空配置,但它仍然失败并出现相同的错误:
@TestConfiguration
static class TestConfig {}
Run Code Online (Sandbox Code Playgroud)
这是我得到的错误:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'failureTaskHandler': Unsatisfied dependency expressed through field 'myManager'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'msgManager': Unsatisfied dependency expressed through field 'inboundManager'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'inboundManager': Unsatisfied dependency expressed through field 'messageRepository'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name …Run Code Online (Sandbox Code Playgroud) 我在 SpringMVC 中有一个 url 路径模式,如下所示:
/person/{personId}/address/{addressId}
Run Code Online (Sandbox Code Playgroud)
我有 personId = 2 和 addressId = 3 有没有一种简单的方法可以让我生成
/person/2/address/3
Run Code Online (Sandbox Code Playgroud)
在 SpringMvc 中使用实用方法?
在此spring-boot项目中,以下操作WebMvcTest失败,因为未找到的GET /items映射ItemController
@RunWith(SpringRunner.class)
@WebMvcTest(ItemController.class)
@AutoConfigureMockMvc
public class Test_ItemController {
@Autowired
private MockMvc mvc;
@MockBean
private ItemDao dao;
@MockBean
private CartDao cartDao;
@Test
public void test() throws Exception {
// setting up mock response
Cart cart = new Cart();
cart.setId(1);
Item item = new Item();
item.setCart(cart);
item.setItemName("toothbrush");
item.setId(1);
//---------------------
List<Item> items = new ArrayList<>();
items.add(item);
given(this.dao.findAll()).willReturn(items);
this.mvc.perform(get("items").accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk());
}
}
Run Code Online (Sandbox Code Playgroud)
错误是:
2018-02-26 12:10:45.816 WARN 12252 --- [ main] o.s.web.servlet.PageNotFound :
No mapping found for HTTP …Run Code Online (Sandbox Code Playgroud) spring spring-mvc spring-mvc-test spring-boot spring-boot-test
我用Spring REST Docs编写API文档。
代码示例:
@Override
public void getById(String urlTemplate, PathParametersSnippet pathParametersSnippet, Object... urlVariables) throws Exception {
resultActions = mockMvc.perform(get(urlTemplate, urlVariables)
.principal(principal)
.contentType(APPLICATION_JSON))
.andExpect(status().isOk())
.andDo(print());
// do..
}
Run Code Online (Sandbox Code Playgroud)
但是问题是测试结果只能在一行中回答。而且,了解返回数据的结构非常困难。
响应示例:
MockHttpServletResponse:
Status = 200
Error message = null
Headers = {Content-Type=[application/json;charset=UTF-8]}
Content type = application/json;charset=UTF-8
Body = {"creator":null,"modifier":null,"modificationTime":null,"creationTime":null,"id":100,"deleted":false,"name":"Name","description":null,"report":[{"creator":"System","modifier":"System","modificationTime":"2019-01-30T14:21:50","creationTime":"2019-01-30T14:21:50","id":1,"name":"Form name","reportType":{"creator":"System","modifier":"System","modificationTime":"2019-01-30T14:21:50","creationTime":"2019-01-30T14:21:50","id":1,"deleted":false,"name":"Raport"},"unmodifiable":true}]}
Forwarded URL = null
Redirected URL = null
Cookies = []
Run Code Online (Sandbox Code Playgroud)
此外,我根据收到的答案生成文档,并且在文档中还使用未格式化的JSON
我究竟做错了什么?如何启用JSON格式?
spring-mvc-test ×13
java ×6
spring ×6
spring-mvc ×6
spring-boot ×5
junit ×3
json ×2
unit-testing ×2
maven ×1
mockmvc ×1
mongodb ×1
rest ×1
spring-data ×1