[英]Unit Test of file upload using MockMvcBuilders with standalone context and SpringBoot 1.2.5
我正在使用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對其進行了測試,並且一切都按預期進行。 不幸的是,我無法為該代碼編寫獨立的單元測試。 當前的單元測試是:
@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
不能訪問它。
我嘗試了多種配置的單元測試,為簡潔起見,我沒有報告。 特別是,我也試過休息,保證如圖所示這里 ,但說實話,這並不工作,因為它似乎我不能嘲笑AService
實例。
有什么辦法嗎?
您正在嘗試在此處將單元測試( standaloneSetup(controller).build();
)與Spring集成測試( @RunWith(SpringJUnit4ClassRunner.class)
) @RunWith(SpringJUnit4ClassRunner.class)
。
做一個或另一個。
集成測試將需要使用類似下面的代碼。 問題可能是假豆。 有幾種方法可以使用@Primary
注釋和@Profile
注釋來偽造此類bean(您創建了將覆蓋主要生產bean的測試bean)。 我的Spring bean的這種偽造的一些例子(如這個bean被替換成了這個bean在本次測試 )。
@Autowired private WebApplicationContext webApplicationContext; @BeforeMethod public void init() { mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); }
Secodn選項是在沒有Spring Context獨立安裝的情況下,在測試和測試控制器上刪除@RunWith(SpringJUnit4ClassRunner.class)
和其他類級別的配置。 這樣,您就無法在控制器上測試驗證注釋,但是可以使用Spring MVC注釋。 優點是可以通過Mockito偽造豆子(例如,通過InjectMocks和Mock注釋)
我混合了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
}
該錯誤表明該請求不是多部分請求。 換句話說,到那時它有望被解析。 但是,在MockMvc測試中,沒有實際的請求。 這只是模擬請求和響應。 因此,您需要使用perform.fileUpload(...)來設置模擬文件上傳請求。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.