我正在使用Spring Boot 1.2.5-RELEASE。我有一个接收MultipartFile
和String
@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);
}
}
现在,该服务运作良好。我用PostMan进行了测试,eveything正如预期的那样。 不幸的是,我无法为该代码编写独立的单元测试。目前的单元测试是:
@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
是自动配置的。但是,我认为standaloneSetup
的{{1}}我无法访问此内容。
我尝试了几种单元测试配置,为简洁起见我没有报告。特别是,我也尝试了如here所示的放心,但老实说这不起作用,因为我似乎无法模仿MockMvcBuilders
实例。
任何解决方案?
答案 0 :(得分:1)
您正在尝试将此单元测试(standaloneSetup(controller).build();
)与Spring集成测试(@RunWith(SpringJUnit4ClassRunner.class)
)结合使用。
做其中一个。
集成测试需要使用类似下面的代码。问题是假装豆子。有一些方法可以使用@Primary
注释和@Profile
注释伪造这样的bean(您创建将覆盖主生产bean的测试bean)。我有一些关于Spring bean伪造的例子(例如this bean中的this bean替换为this test。
@Autowired
private WebApplicationContext webApplicationContext;
@BeforeMethod
public void init() {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
Secodn选项是删除测试和测试控制器上的@RunWith(SpringJUnit4ClassRunner.class)
和其他类级配置,而不使用独立安装的Spring Context。这样您就无法在控制器上测试验证注释,但您可以使用Spring MVC注释。优势是可以通过Mockito伪豆(例如通过InjectMocks和Mock注释)
答案 1 :(得分:1)
我混合了lkrnak建议的内容和Mockito @Spy
的功能。我使用REST-Assured来进行呼叫。所以,我做了如下:
@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
}
答案 2 :(得分:0)
错误表明请求不是多部分请求。换句话说,在那时它预计会被解析。但是在MockMvc测试中没有实际的请求。这只是模拟请求和响应。所以你需要使用perform.fileUpload(...)来设置模拟文件上传请求。