Java 使用具有独立上下文和SpringBoot 1.2.5的MockMvcBuilders进行文件上载的单元测试
我使用的是Spring Boot 1.2.5版本。我有一个控制器,它接收一个Java 使用具有独立上下文和SpringBoot 1.2.5的MockMvcBuilders进行文件上载的单元测试,java,spring,unit-testing,spring-mvc,multipartform-data,Java,Spring,Unit Testing,Spring Mvc,Multipartform Data,我使用的是Spring Boot 1.2.5版本。我有一个控制器,它接收一个多部分文件和一个字符串 @RestController @RequestMapping("file-upload") public class MyRESTController { @Autowired private AService aService; @RequestMapping(method = RequestMethod.POST, consumes = MediaType.MULTIPART
多部分文件
和一个字符串
@RestController
@RequestMapping("file-upload")
public class MyRESTController {
@Autowired
private AService aService;
@RequestMapping(method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@ResponseStatus(HttpStatus.CREATED)
public void fileUpload(
@RequestParam(value = "file", required = true) final MultipartFile file,
@RequestParam(value = "something", required = true) final String something) {
aService.doSomethingOnDBWith(file, value);
}
}
现在,服务很好。我和邮递员一起测试过,一切都如期进行。
不幸的是,我无法为该代码编写独立的单元测试。当前的单元测试是:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MyApplication.class)
@WebAppConfiguration
public class ControllerTest{
MockMvc mockMvc;
@Mock
AService aService;
@InjectMocks
MyRESTController controller;
@Before public void setUp(){
MockitoAnnotations.initMocks(this);
this.mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
}
@Test
public void testFileUpload() throws Exception{
final File file = getFileFromResource(fileName);
//File is correctly loaded
final MockMultipartFile multipartFile = new MockMultipartFile("aMultiPartFile.txt", new FileInputStream(file));
doNothing().when(aService).doSomethingOnDBWith(any(MultipartFile.class), any(String.class));
mockMvc.perform(
post("/file-upload")
.requestAttr("file", multipartFile.getBytes())
.requestAttr("something", ":(")
.contentType(MediaType.MULTIPART_FORM_DATA_VALUE))
.andExpect(status().isCreated());
}
}
测试失败,原因是
java.lang.IllegalArgumentException: Expected MultipartHttpServletRequest: is a MultipartResolver configured?
现在,在Spring Boot的MultipartAutoConfiguration
类中,我看到一个MultipartResolver
是自动配置的。但是,我想通过MockMvcBuilders
的standaloneSetup
,我无法访问它
我尝试了几个单元测试的配置,为了简洁起见,我没有报告这些配置。特别是,我还尝试了如图所示的rest-assured,但老实说,这不起作用,因为我似乎无法模拟AService
实例
有什么解决方案吗?您试图在这里将单元测试(
standaloneSetup(controller.build();
)与Spring集成测试(@RunWith(SpringJUnit4ClassRunner.class)
)结合起来
做一个或另一个
@Primary
注释和@Profile
注释来伪造这样的bean(您创建的测试bean将覆盖主生产bean)。我有一些假冒春豆的例子(例如,被in替换)
@RunWith(SpringJUnit4ClassRunner.class)
和其他类级配置,而不使用独立设置的Spring上下文。这样,您就不能在控制器上测试验证注释,但可以使用SpringMVC注释。优点是可以通过Mockito(例如通过injectmock和Mock注释)伪造bean错误表示请求不是由多个部分组成的请求。换句话说,在这一点上,它应该已经被解析了。然而,在MockMvc测试中没有实际的请求。这只是模拟请求和响应。因此,您需要使用perform.fileUpload(…)来设置模拟文件上传请求。我混合了建议和Mockito
@Spy
功能。我用“放心”来打电话。因此,我做了如下工作:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MyApplication.class)
@WebAppConfiguration
@IntegrationTest({"server.port:0"})
public class ControllerTest{
{
System.setProperty("spring.profiles.active", "unit-test");
}
@Autowired
@Spy
AService aService;
@Autowired
@InjectMocks
MyRESTController controller;
@Value("${local.server.port}")
int port;
@Before public void setUp(){
RestAssured.port = port;
MockitoAnnotations.initMocks(this);
}
@Test
public void testFileUpload() throws Exception{
final File file = getFileFromResource(fileName);
doNothing().when(aService)
.doSomethingOnDBWith(any(MultipartFile.class), any(String.class));
given()
.multiPart("file", file)
.multiPart("something", ":(")
.when().post("/file-upload")
.then().(HttpStatus.CREATED.value());
}
}
该服务定义为
@Profile("unit-test")
@Primary
@Service
public class MockAService implements AService {
//empty methods implementation
}
第二个选项不起作用:我删除了测试类的所有注释,从您提到的注释开始,但结果是:
org.springframework.web.util.NestedServletException:请求处理失败;嵌套异常为java.lang.IllegalArgumentException:预期的MultipartTTpServletRequest:是否配置了MultipartResolver?
。现在我尝试第一种方法。第一种方法有一些缺点。假设我使用了几个服务,并且我想测试几个行为。然后,我必须在为集成测试概要文件定义的服务中定义不同行为的选项。您原来的方法根本不起作用。没有机会。我只是列举了两种方法,即如何进行MockMvc测试。你必须用一个或另一个来解决这个问题。你能写一个完整的例子吗?这里举个例子
@Profile("unit-test")
@Primary
@Service
public class MockAService implements AService {
//empty methods implementation
}