Issue
after fixing a bug in an older Java Spring MVC 4.1 application, I wanted to add a unit test, but the method the current code base is using for testing won't actually execute validation.
So I wanted to add MVCMock, but when it executes the validation methods, the values passed to isValid
is always null.
Relevant files below (I've tried to strip out as much noise as possible):
// Unit Test
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@EnableWebMvc
@ContextConfiguration(locations = {"/applicationContext-test.xml"})
public class ExampleControllerTest extends AbstractControllerTestBase {
@Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
@Before
public void setup() {
this.mockMvc = webAppContextSetup(this.context).build();
}
@Test
public void fileUploadZipArchive() throws Exception {
// Upload a zip file
File mockFile = new File("src/test/resources/fixtures/ex.zip");
MockHttpServletRequestBuilder multipart = MockMvcRequestBuilders
.fileUpload("/files/ex/upload/Tex")
.file("ex.zip", FileUtils.readFileToByteArray(mockFile));
MvcResult result = mockMvc.perform(multipart)
.andReturn();
}
// Bean
public class FileUploadBean {
@Valid
@MultipartMimeTypeMatch
private MultipartFile file = null;
// ...
}
// Validator
public class MultipartMimeTypeMatchValidator implements ConstraintValidator<MultipartMimeTypeMatch, Object> {
// ...
public boolean isValid(Object value, final ConstraintValidatorContext context) {
// value and context is always null
}
}
// Controller
@RequestMapping(value = "/files/{ex1}/upload/{ex2}", method = RequestMethod.POST)
public Object uploadFile(HttpServletRequest request, @PathVariable String ex1,
@PathVariable String ex2, @Valid FileUploadBean fileUploadBean, BindingResult result) throws IllegalStateException, IOException {
// ...
}
}
What could be going wrong?
NOTE: Spring 4.1
Solution
The javadoc of the file
method states that the name
should be the name of the file. I agree that that is a bit misleading. Instead it should be the name of the request parameter to use, which should be (generally speaking) the same as the property in your model object.
.file("ex.zip", FileUtils.readFileToByteArray(mockFile));
With this a request parameter named ex.zip
will be part of the request, however you have one that is named file
.
.file("file", FileUtils.readFileToByteArray(mockFile));
Using the above line should fix it and properly bind to your object in turn properly invoking your validator.
On a side node, your validator should properly handle the null
case as well or add a @NotNull
on the field as well. The @Valid
on the field doesn't do anything so you can remove that.
Answered By - M. Deinum
Answer Checked By - Senaida (JavaFixing Volunteer)