Mithrand1r
Mithrand1r

Reputation: 2353

Spring boot rest api mockito + mockmvc persistence

I would like to create Test for my rest controller:

@Controller
@RequestMapping("/v2/api/show/project")
public class ApiAccessController {
    private final ApiAccessService apiAccessService;

    @Autowired
    ApiAccessController(ApiAccessService apiAccessService){
        this.apiAccessService = apiAccessService;
    }
    @PutMapping(value = "/{id}/apikey")
    public ResponseEntity<ApiKeyResponse> generateApiKey(@PathVariable("id")Long id, Principal principal) {
        return apiAccessService.generateApiKey(id, principal.getName());
    }
}

My test looks as follow:

@RunWith(SpringJUnit4ClassRunner.class)
public class ApiAccessControllerTest {
    private MockMvc mockMvc;
    Principal principal = new Principal() {
        @Override
        public String getName() {
            return "TEST_PRINCIPAL";
        }
    };

    @InjectMocks
    ApiAccessController apiAccessController;
    @Mock
    ProjectRepository projectRepository;

    @Before
    public void setUp(){
        mockMvc = MockMvcBuilders.standaloneSetup(apiAccessController).build();
    }
    @Test
    public void testGenerateApiKey() throws Exception {
        Project project = new Project();
        project.setId((long) 1);
        project.setName("test");
        project.setDescription("testdesc");
        project.setCiid("ciid");
        when(projectRepository.save(any(Project.class))).thenReturn(project);
        mockMvc.perform(MockMvcRequestBuilders.put("/v2/api/show/project/" + project.getId() +"/apikey").principal(principal))
                .andExpect(MockMvcResultMatchers.status().isOk());
    }
}

Which is ment to create project and then run generateApiKey on this project, however I get NullpointerException looking like mocked controller cannot find created entity

could anyone please point me in the right direction as I am just starting with testing?

Upvotes: 0

Views: 272

Answers (2)

i.bondarenko
i.bondarenko

Reputation: 3572

You should mock ApiAccessService instead of ProjectRepository. Have a look at the code:

@RunWith(SpringJUnit4ClassRunner.class)
public class ApiAccessControllerTest {
    private MockMvc mockMvc;
    private Principal principal = () -> "TEST_PRINCIPAL";

    @InjectMocks
    private ApiAccessController apiAccessController;

    @Mock
    private ApiAccessService apiAccessService;

    @Before
    public void setUp() {
        mockMvc = MockMvcBuilders.standaloneSetup(apiAccessController).build();
    }

    @Test
    public void testGenerateApiKey() throws Exception {
        long id = 1L;
        when(apiAccessService.generateApiKey(id, principal.getName())).thenReturn(new ApiKeyResponse(111L));

        mockMvc.perform(MockMvcRequestBuilders.put("/v2/api/show/project/{id}/apikey", id).principal(principal))
                .andExpect(MockMvcResultMatchers.status().isOk());
    }
}

If you want to create integration test, that tests ApiAccessController -> ApiAccessService -> ProjectRepository integration you need to load your context (use for example @SpringBootTest).

Also you need to fix controller, use ResponseEntity.ok(...) :

@PutMapping(value = "/{id}/apikey")
public ResponseEntity<ApiKeyResponse> generateApiKey(@PathVariable("id") Long id, Principal principal) {
    return ResponseEntity.ok(apiAccessService.generateApiKey(id, principal.getName()));
}

You can find really good examples of all test types in this repository MVC tests examples

Upvotes: 1

Christian Frommeyer
Christian Frommeyer

Reputation: 1420

The Mock you are creating is not referenced in the Controller. The Service you reference in the Controller is not part of your test setup. Therefore any access to the Service will cause a NullPointerException as the Service is not set.

Upvotes: 0

Related Questions