使用Spring 3.1.2,JUnit 4.10.0,这两个版本都很新.我遇到的问题是我无法使基于注释的自动装配工作.
下面是两个样本,一个没有使用注释,这是正常工作.而第二个使用注释,这是行不通的,我找不到原因.我几乎遵循了spring-mvc-test的样本.
工作:
package com.company.web.api;
// imports
public class ApiTests {
@Test
public void testApiGetUserById() throws Exception {
ApplicationContext ctx = new ClassPathXmlApplicationContext("/com/company/web/api/ApiTests-context.xml");
UserManagementService userManagementService = (UserManagementService) ctx.getBean("userManagementService");
ApiUserManagementController apiUserManagementController = new ApiUserManagementController(userManagementService);
MockMvc mockMvc = standaloneSetup(apiUserManagementController).build();
// The actual test
mockMvc.perform(get("/api/user/0").accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk());
}
}
Run Code Online (Sandbox Code Playgroud)
失败,因为userManagementService为空,没有获得自动连接:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration // should default to ApiTests-context.xml in same package
public class ApiTests {
@Autowired
UserManagementService userManagementService;
private MockMvc mockMvc;
@Before
public void setup(){
// SetUp never gets called?! …Run Code Online (Sandbox Code Playgroud) 今天开始在办公室学习Spring Test MVC框架,它看起来很方便,但是直接面对一些严重的麻烦.花了几个小时谷歌搜索,但找不到与我的问题有关的任何事情.
这是我非常简单的测试类:
import static org.hamcrest.Matchers.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.context.WebApplicationContext;
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = WebAppContext.class)
public class ControllerTests {
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setup() {
mockMvc = webAppContextSetup(wac).build();
}
@Test
public void processFetchErrands() throws Exception {
mockMvc.perform(post("/errands.do?fetchErrands=true"))
.andExpect(status().isOk())
.andExpect(model().attribute("errandsModel", allOf(
hasProperty("errandsFetched", is(true)),
hasProperty("showReminder", is(false)))));
}
}
Run Code Online (Sandbox Code Playgroud)
测试到达以下控制器,但if由于未正确授权,因此在第一个条款上失败.
@RequestMapping(method …Run Code Online (Sandbox Code Playgroud) 我在Spring Boot中运行一个简单的Junit测试控制器.测试代码如下所示:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {FrontControllerApplication.class})
@WebAppConfiguration
@ComponentScan
@IntegrationTest({"server.port:0", "eureka.client.registerWithEureka:false", "eureka.client.fetchRegistry:false"})
@ActiveProfiles("integrationTest")
public class MyControllerIT {
Run Code Online (Sandbox Code Playgroud)
在application-integrationTest.properties中,我有以下Eureka设置:
####### Eureka
eureka.serviceUrl.default=http://localhost:8767/eureka/
eureka.printDeltaFullDiff=false
eureka.client.refresh.interval=1
eureka.appinfo.replicate.interval=1
eureka.serviceUrlPollIntervalMs=1000
eureka.name=${spring.application.name}
####### Netflix Eureka #######
eureka.client.serviceUrl.defaultZone=http://localhost:8767/eureka/
eureka.client.instanceInfoReplicationIntervalSeconds=1
eureka.client.initialInstanceInfoReplicationIntervalSeconds=0
eureka.instance.virtualHostName=${spring.application.name}
eureka.instance.preferIpAddress=true
eureka.instance.initialStatus=DOWN
eureka.instance.leaseRenewalIntervalInSeconds=3
eureka.instance.leaseExpirationDurationInSeconds=10
eureka.instance.metadataMap.instanceId=${spring.application.name}:${spring.application.instance_id:${random.value}}
eureka.eurekaserver.connectionIdleTimeoutInSeconds=5
eureka.responseCacheAutoExpirationInSeconds=5
Run Code Online (Sandbox Code Playgroud)
当junit测试开始时,我看到以下内容:
2015-09-16 16:46:03,905 ERROR localhost-startStop-1 com.netflix.discovery.DiscoveryClient Can't get a response from http://localhost:8767/eureka/apps/
Can't contact any eureka nodes - possibly a security group issue?
com.sun.jersey.api.client.ClientHandlerException: java.net.ConnectException: Connection refused: connect
at com.sun.jersey.client.apache4.ApacheHttpClient4Handler.handle(ApacheHttpClient4Handler.java:184) ~[jersey-apache-client4-1.11.jar:1.11]
测试通过,这不是问题,但我看到很多与Eureka有关的异常堆栈跟踪.问题是,是否有办法模拟尤里卡或其他方式在进行测试时跳过它?
如果测试失败并且tst运行得更快,则更容易看到相关的堆栈跟踪
我在为测试设置会话属性时遇到问题.我正在使用MockMvc来测试对控制器的调用.会话模型上有一个成员属性(表示已登录的人).SessionModel对象被添加为会话属性.我期待它在下面的formBacking方法的ModelMap参数中填充,但ModelMap始终为空.
在通过webapp运行时,控制器代码工作正常,但在JUnit中则不行.知道我可能做错了吗?
这是我的JUnit测试
@Test
public void testUnitCreatePostSuccess() throws Exception {
UnitCreateModel expected = new UnitCreateModel();
expected.reset();
expected.getUnit().setName("Bob");
SessionModel sm = new SessionModel();
sm.setMember(getDefaultMember());
this.mockMvc.perform(
post("/units/create")
.param("unit.name", "Bob")
.sessionAttr(SessionModel.KEY, sm))
.andExpect(status().isOk())
.andExpect(model().attribute("unitCreateModel", expected))
.andExpect(view().name("tiles.content.unit.create"));
}
Run Code Online (Sandbox Code Playgroud)
这是有问题的控制器
@Controller
@SessionAttributes({ SessionModel.KEY, UnitCreateModel.KEY })
@RequestMapping("/units")
public class UnitCreateController extends ABaseController {
private static final String CREATE = "tiles.content.unit.create";
@Autowired
private IUnitMemberService unitMemberService;
@Autowired
private IUnitService unitService;
@ModelAttribute
public void formBacking(ModelMap model) {
SessionModel instanceSessionModel = new SessionModel();
instanceSessionModel.retrieveOrCreate(model);
UnitCreateModel instanceModel = new UnitCreateModel();
instanceModel.retrieveOrCreate(model); …Run Code Online (Sandbox Code Playgroud) 我使用Spring Boot创建了一个文件上传服务,并使用Spring Mock Mvc和MockMultipartFile进行测试.我想测试是否在超出最大文件大小时抛出错误.以下测试失败,因为它收到200.
RandomAccessFile f = new RandomAccessFile("t", "rw");
f.setLength(1024 * 1024 * 10);
InputStream is = Channels.newInputStream(f.getChannel());
MockMultipartFile firstFile = new MockMultipartFile("data", "file1.txt", "text/plain", is);
mvc.perform(fileUpload("/files")
.file(firstFile))
.andExpect(status().isInternalServerError());
Run Code Online (Sandbox Code Playgroud)
有没有可能测试上传文件的大小?
这是我对Spring Controller的测试用例
@RunWith(SpringRunner.class)
@WebMvcTest(value = MyController.class)
public class MyControllerTest {
@MockBean
private MyService myService;
}
Run Code Online (Sandbox Code Playgroud)
所以这是一个专门针对MyController中的方法的单元测试.但是当我运行测试时,Spring似乎开始实例化OtherController及其所有依赖项.
我已经尝试将上面的内容更新为
@RunWith(SpringRunner.class)
@WebMvcTest(value = MyController.class, excludeFilters = @ComponentScan.Filter(value= OtherController.class, type = FilterType.ANNOTATION))
public class MyControllerTest {
...
}
Run Code Online (Sandbox Code Playgroud)
但是春天似乎仍然有线.这是Spring抛出的错误,因为它在我特意运行上面的测试时试图实例化OtherController.
2017-01-06 12:09:46.207 WARN 18092 --- [ main] o.s.w.c.s.GenericWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'otherController' defined in file [C:\..OtherController.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name …Run Code Online (Sandbox Code Playgroud) 我正在使用JUnit来测试我的Spring MVC控制器.下面是我的方法,它返回一个index.jsp页面并Hello World在屏幕上显示 -
@RequestMapping(value = "index", method = RequestMethod.GET)
public HashMap<String, String> handleRequest() {
HashMap<String, String> model = new HashMap<String, String>();
String name = "Hello World";
model.put("greeting", name);
return model;
}
Run Code Online (Sandbox Code Playgroud)
以下是我对上述方法的JUnit测试:
public class ControllerTest {
private MockMvc mockMvc;
@Before
public void setup() throws Exception {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
this.mockMvc = standaloneSetup(new Controller()).setViewResolvers(viewResolver).build();
}
@Test
public void test01_Index() throws Exception {
mockMvc.perform(get("/index")).andExpect(status().isOk()).andExpect(content().contentType("application/json"))
.andExpect(jsonPath("$.greeting").value("Hello World"));
}
}
Run Code Online (Sandbox Code Playgroud)
当我调试它时,junit上面运行正常但是当我运行junit时run as junit,它给了我这个错误 …
我正在使用spring-test-mvc测试我的控制器,但我找不到打印请求体的方法,这非常不方便.
与MockMvcResultHandlers.print()
mvc.perform(put("/payment/1234")
.content("{\"amount\":2.3")
.contentType(MediaType.APPLICATION_JSON))
.andDo(print());
Run Code Online (Sandbox Code Playgroud)
我找到了一些身体信息,但没有找到身体部位:
MockHttpServletRequest:
HTTP Method = PUT
Request URI = /payment/1234
Parameters = {}
Headers = {Content-Type=[application/json]}
Handler:
Type = com.restbucks.ordering.rest.PaymentResource
Method = public org.springframework.hateoas.Resource<com.restbucks.ordering.domain.Payment> com.restbucks.ordering.rest.PaymentResource.handle(com.restbucks.ordering.commands.MakePaymentCommand)
Async:
Async started = false
Async result = null
Run Code Online (Sandbox Code Playgroud)
更新
在阅读了一些源代码之后,似乎我应该扩展MockMvcResultHandlers来添加一些打印项目?
//PrintingResultHandler.java
protected void printRequest(MockHttpServletRequest request) throws Exception {
this.printer.printValue("HTTP Method", request.getMethod());
this.printer.printValue("Request URI", request.getRequestURI());
this.printer.printValue("Parameters", getParamsMultiValueMap(request));
this.printer.printValue("Headers", getRequestHeaders(request));
// add body print?
}
Run Code Online (Sandbox Code Playgroud)
更新 概念证明代码:
public static class CustomMockMvcResultHandlers {
public static ResultHandler print() {
return new ConsolePrintingResultHandler(); …Run Code Online (Sandbox Code Playgroud) 我需要测试我的控制器方法,包括删除方法.这是部分控制器代码:
@RestController
@RequestMapping("/api/foo")
public class FooController {
@Autowired
private FooService fooService;
// other methods which works fine in tests
@RequestMapping(path="/{id}", method = RequestMethod.DELETE)
public void delete(@PathVariable Long id) {
fooService.delete(id);
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的测试:
@InjectMocks
private FooController fooController;
@Before
public void setUp() {
this.mockMvc = MockMvcBuilders.standaloneSetup(fooController)
.setControllerAdvice(new ExceptionHandler()).alwaysExpect(MockMvcResultMatchers.content().contentType("application/json;charset=UTF-8")).build();
}
@Test
public void testFooDelete() throws Exception {
this.mockMvc.perform(MockMvcRequestBuilders
.delete("/api/foo")
.param("id", "11")
.contentType(MediaType.APPLICATION_JSON))
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
}
Run Code Online (Sandbox Code Playgroud)
因错误的状态代码而导致测试失败:
java.lang.AssertionError:预期状态:200实际:400
在控制台日志中我也发现了这个:
2017-12-11 20:11:01 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - DispatcherServlet with name '' processing DELETE request for …Run Code Online (Sandbox Code Playgroud) 我有一个简单的健康控制器定义如下:
@RestController
@RequestMapping("/admin")
public class AdminController {
@Value("${spring.application.name}")
String serviceName;
@GetMapping("/health")
String getHealth() {
return serviceName + " up and running";
}
}
Run Code Online (Sandbox Code Playgroud)
以及测试它的测试类:
@WebMvcTest(RedisController.class)
class AdminControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
public void healthShouldReturnDefaultMessage() throws Exception {
this.mockMvc.perform(get("/admin/health"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().string(containsString("live-data-service up and running")));
}
}
Run Code Online (Sandbox Code Playgroud)
运行测试时,我收到以下错误:
***************************
APPLICATION FAILED TO START
***************************
Description:
Field configuration in com.XXXX.LiveDataServiceApplication required a bean of type 'com.XXXXX.AppConfiguration' that could not be found.
The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true) …Run Code Online (Sandbox Code Playgroud) spring-test-mvc ×10
spring ×8
java ×5
spring-boot ×4
junit ×3
spring-mvc ×2
spring-test ×2
unit-testing ×2
junit4 ×1
mockito ×1
rest ×1