Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to write unit test case for controller class using mockito

I am very new to Mockito and jUnit and I try to learn the right way to do TDD. I need couples of example so that i can write unit test using mockito

Following is my controller class which upload file and perform some action on this file inputs.

@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);
    }

}

can any body please suggest some example how can I write test case for this using mockito?

Edit I have write down following test class but how to proceed further

@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);

    }

}
like image 266
Raje Avatar asked Jan 17 '12 12:01

Raje


People also ask

How do you write a unit test for controller class?

Writing a Unit Test for REST Controller First, we need to create Abstract class file used to create web application context by using MockMvc and define the mapToJson() and mapFromJson() methods to convert the Java object into JSON string and convert the JSON string into Java object.


1 Answers

There are a couple things you seem to have crossed up in your test. There are integration tests and unit tests. Integration tests will test everything (or almost everything) all hooked up - so you use Spring configuration files very close to the real ones and real examples of objects get injected to your class under test. That's mostly what I use @ContextConfiguration but I use that in conjunction with @RunWith(SpringJUnit4ClassRunner.class)

If you are using Mockito (or any mocking framework), it is usually because you want to isolate the class you are testing from real implementations of other classes. So instead of, for example, having to contrive a way to get your RegistrationService to throw a NumberFormatException to test that code path, you just tell the mock RegistrationService to do it. There are lots of other examples where it is more convenient to use mocks than to use real class instances.

So, that mini-lesson finished. Here is how I would re-write your test class (with an extra example and commented along the way).

@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, result, 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", nextPage,
                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, result, model);
    }
}
like image 140
jhericks Avatar answered Nov 11 '22 17:11

jhericks