1

I have a simple Java Spring REST API application and i don't know how can i unit test it. I have read the documentations of JUnit and Mockito, but i couldn't figure it out.

Here is the post method in the StudentController class

@RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
    public void insertStudent(@RequestBody Student student){
        studentService.insertStudent(student);
    }

And here is the insertStudent method in the StudentService class

public void insertStudent(Student student) {
        studentDao.insertStudent(student);
    }

I use MySQL for database. Should i use database too for unit test? I mean i don't want any integration test. I want only unit test. I use supertest in Node.js and it takes care for all, can i do that with JUnit or Mockito too?

Adam Jungen
  • 407
  • 2
  • 7
  • 23
  • 1
    A mockist unit test of the controller would mock out the service and ensure the correct method gets called, which you can certainly do with JUnit+Mockito. Then no database is needed, because the real service isn't being used at all. – jonrsharpe Oct 07 '17 at 11:56
  • @jonrsharpe can you give me a link which shows how i can do that? – Adam Jungen Oct 07 '17 at 12:00
  • There are loads of examples out there already, I'd recommend research. See e.g. https://stackoverflow.com/q/10906945/3001761 – jonrsharpe Oct 07 '17 at 12:01

3 Answers3

8

If you want to do unit testing then you would not have to connect to the DB. Connecting to DB's and other external services would be considered integration testing. So the request to the DB would be mocked out when testing your StudentService class.

Second point worth mentioning is that you would test your controller class and you service class separately, but in your case those tests would look very similar.

Below is one way you can test your controller's insertStrundent method.

@RunWith(MockitoJUnitRunner.class)
public class TestStudentContoller {

    @Mock
    StundentService mockStudentService;
    @InjectMocks
    StudentController studentController = new StudentController();

    @Test
    public void testInsertStudent(){
    
        Student student = new Student();

        studentContoller.insertStudent(student);
    
        verify(studentService, times(1)).insertStudent(student);
    }

Since you controller's insertStudent method has no if statements and only one branch, there is basically only one test that needs to be performed, basically does the controller call the service.

Another way it can be tested is with Springs MockMvc. The good thing about the MockMvc is that it lets you test the HTTP request. For example in this case you would want to test that your controller's insertStudent method will properly respond to HTTP POST requests with a JSON Student.

@RunWith(MockitoJUnitRunner.class)
public class TestStudentContoller {

    @Mock
    StundentService mockStudentService;
    @InjectMocks
    StudentController studentController = new StudentController();

    MockMvc mockMvc;

    @Before
    public void setup(){
        mockMvc = MockMvcBuilders.standAloneSetup(studentController).build();
    }

    @Test
    public void testInsertStudent(){

        mockMvc.perform(post("path/to/insert/student")
            .accept(MediaType.APPLICATION_JSON)
            .andExpect(status().isOk())
            .andExpect(content().string("{}"));//put json student in here
    
        verify(studentService, times(1)).insertStudent(student);
    }

MockMvc has other cool methods you should explore.

Jose Martinez
  • 11,452
  • 7
  • 53
  • 68
2

I have a simple Java Spring REST API application

You should really start earlier to think about unittests. The best way to do them is before the production code implements the (new) behavior (TDD).

Here is the post method in the StudentController class

@RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
    public void insertStudent(@RequestBody Student student){
        studentService.insertStudent(student);
    }

This code is too simple to fail. Writing unittests for such code is a waist of time. Code like this is tested via application or module tests

I would start writing unittests for this code as soon as there is some decision to make (e.g.: additional calls to other objects depending on the input parameters).

The point here is that unittests do not test code - unittests verify desired behavior (which is expressed in your requirements). So yes: not testing this method reduces the coverage in your reports. But the number any coverage tool calculates is less important than the requirement coverage which no tool can calculate and which you can only guarantee by doing TDD.

Timothy Truckle
  • 15,071
  • 2
  • 27
  • 51
  • 1
    I don't agree with "Writing unittests for such code is a 'waist' of time". OP is looking for a way to test it and there are ways (like others have suggested) to do that. – old_soul_on_the_run Feb 04 '20 at 04:54
0

You want to mock studentService and have a unit test that verify that when the method insertStudent(Student) of the API is called then there is exactly one call to the service's insertStudent(Student) with the same Student instance.

Then create unit tests for different scenario, i.e handling nulls etc..