簡體   English   中英

使用具有獨立上下文和SpringBoot 1.2.5的MockMvcBuilders進行文件上傳的單元測試

[英]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是自動配置的。 但是,我想使用MockMvcBuildersstandaloneSetup不能訪問它。

我嘗試了多種配置的單元測試,為簡潔起見,我沒有報告。 特別是,我也試過休息,保證如圖所示這里 ,但說實話,這並不工作,因為它似乎我不能嘲笑AService實例。

有什么辦法嗎?

您正在嘗試在此處將單元測試( standaloneSetup(controller).build(); )與Spring集成測試( @RunWith(SpringJUnit4ClassRunner.class)@RunWith(SpringJUnit4ClassRunner.class)

做一個或另一個。

  1. 集成測試將需要使用類似下面的代碼。 問題可能是假豆。 有幾種方法可以使用@Primary注釋和@Profile注釋來偽造此類bean(您創建了將覆蓋主要生產bean的測試bean)。 我的Spring bean的這種偽造的一些例子(如這個bean被替換成了這個bean本次測試 )。

     @Autowired private WebApplicationContext webApplicationContext; @BeforeMethod public void init() { mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); } 
  2. 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM