我对Mockito和jUnit非常新,我尝试学习正确的TDD方式.我需要几个例子,以便我可以使用mockito来编写单元测试
@Controller @RequestMapping("/registration") public class RegistrationController { @Autowired private RegistrationService RegistrationService; @Value("#{Properties['uploadfile.location']}") private String uploadFileLocation; public RegistrationController() { } @RequestMapping(method = RequestMethod.GET) public String getUploadForm(Model model) { model.addAttribute(new Registration()); return "is/Registration"; } @RequestMapping(method = RequestMethod.POST) public String create(Registration registration,BindingResult result,ModelMap model) throws NumberFormatException,Exception { File uploadedFile = uploadFile(registration); List<Registration> userDetails = new ArrayList<Registration>(); processUploadedFile(uploadedFile,userDetails); model.addAttribute("userDetails",userDetails); return "registration"; } private File uploadFile(Registration registration) { Date dt = new Date(); SimpleDateFormat format = new SimpleDateFormat("MM_dd_yyyy_HH_mm_ss"); File uploadedFile = new File(uploadFileLocation + registration.getFileData().getOriginalFilename() + "." + format.format(dt)); registration.getFileData().transferTo(uploadedFile); return uploadedFile; } private void processUploadedFile(File uploadedFile,List<Registration> userDetails) throws NumberFormatException,Exception { registrationService.processFile(uploadedFile,userDetails); } }
可以任何身体请建议一些例子我如何使用mockito来编写测试用例?
编辑
我已经写下了下面的测试类,但如何进一步
@RunWith(MockitoJUnitRunner.class) @ContextConfiguration(locations = { "/Meta-INF/spring/applicationContext.xml"}) public class BulkRegistrationControllerTest { @InjectMocks private RegistrationService registrationService= new RegistrationServiceImpl(); @Mock private final ModelMap model=new ModelMap(); @InjectMocks private ApplicationContext applicationContext; private static MockHttpServletRequest request; private static MockHttpServletResponse response; private static RegistrationController registrationController; @BeforeClass public static void init() { request = new MockHttpServletRequest(); response = new MockHttpServletResponse(); registrationController = new RegistrationController(); } public void testCreate() { final String target = "bulkRegistration"; BulkRegistration bulkRegistration=new BulkRegistration(); final BindingResult result=new BindingResult(); String nextPage=null; nextPage = bulkRegistrationController.create(bulkRegistration,result,model); assertEquals("Controller is not requesting the correct form",nextPage,target); } }
解决方法
有几件事你似乎已经在你的测试中.有集成测试和单元测试.集成测试将测试所有连接的东西(或几乎所有的东西),所以你使用Spring配置文件非常接近真实的实例,并将实际的对象示例注入到被测试的类中.这大部分是我使用@ContextConfiguration,但我结合使用@RunWith(SpringJUnit4ClassRunner.class)
如果您使用Mockito(或任何嘲笑框架),通常是因为您想要从其他类的实际实现中隔离正在测试的类.所以,例如,不必设法让你的RegistrationService抛出一个NumberFormatException来测试这个代码路径,你只需要告诉模拟注册服务.还有很多其他的例子,使用mocks比使用真实类实例更方便.
所以,这个迷你课完成了.这是我将如何重新编写你的测试类(附有一个额外的例子,并在评论的过程中).
@RunWith(MockitoJUnitRunner.class) public class RegistrationControllerTest { // Create an instance of what you are going to test. // When using the @InjectMocks annotation,you must create the instance in // the constructor or in the field declaration. @InjectMocks private RegistrationController controllerUT = new RegistrationController(); // The @Mock annotation creates the mock instance of the class and // automatically injects into the object annotated with @InjectMocks (if // possible). @Mock private RegistrationService registrationService; // This @Mock annotation simply creates a mock instance. There is nowhere to // inject it. Depending on the particular circumstance,it may be better or // clearer to instantiate the mock explicitly in the test itself,but we're // doing it here for illustration. Also,I don't know what your real class // is like,but it may be more appropriate to just instantiate a real one // than a mock one. @Mock private ModelMap model; // Same as above @Mock private BulkRegistration bulkRegistration; // Same as above @Mock private FileData fileData; @Before public void setUp() { // We want to make sure that when we call getFileData(),it returns // something non-null,so we return the mock of fileData. when(bulkRegistration.getFileData()).thenReturn(fileData); } /** * This test very narrowly tests the correct next page. That is why there is * so little expectation setting on the mocks. If you want to test other * things,such as behavior when you get an exception or having the expected * filename,you would write other tests. */ @Test public void testCreate() throws Exception { final String target = "bulkRegistration"; // Here we create a default instance of BindingResult. You don't need to // mock everything. BindingResult result = new BindingResult(); String nextPage = null; // Perform the action nextPage = controllerUT.create(bulkRegistration,model); // Assert the result. This test fails,but it's for the right reason - // you expect "bulkRegistration",but you get "registration". assertEquals("Controller is not requesting the correct form",target); } /** * Here is a simple example to simulate an exception being thrown by one of * the collaborators. * * @throws Exception */ @Test(expected = NumberFormatException.class) public void testCreateWithNumberFormatException() throws Exception { doThrow(new NumberFormatException()).when(registrationService) .processFile(any(File.class),anyList()); BindingResult result = new BindingResult(); // Perform the action controllerUT.create(bulkRegistration,model); } }