MockMvc returns null instead of object

10,629

You're using a mock profileService in your test, and you never tell that mock what to return. So it returns null.

You need something like

when(profileService.create(any(User.class)).thenReturn(new Profile(...));

Note that using

when(profileService.create(user).thenReturn(new Profile(...));

will only work if you properly override equals() (and hashCode()) in the User class, because the actual User instance that the controller receives is a serialized/deserialized copy of the user you have in your test, and not the same instance.

Share:
10,629
user3127632
Author by

user3127632

Web Developer

Updated on July 17, 2022

Comments

  • user3127632
    user3127632 almost 2 years

    I am developing a microservice application and I need to test a post request to a controller. Testing manually works but the test case always returns null.

    I've read many similar questions here in Stackoverflow and documentation but haven't figured out yet what I am missing.

    Here is what I currently have and what I tried in order to make it work:

    //Profile controller method need to be tested
    @RequestMapping(path = "/", method = RequestMethod.POST)
    public ResponseEntity<Profile> createProfile(@Valid @RequestBody User user, UriComponentsBuilder ucBuilder) {
        Profile createdProfile = profileService.create(user); // line that returns null in the test
        if (createdProfile == null) {
            System.out.println("Profile already exist");
            return new ResponseEntity<>(HttpStatus.CONFLICT);
        }
        HttpHeaders headers = new HttpHeaders();
        headers.setLocation(ucBuilder.path("/{name}").buildAndExpand(createdProfile.getName()).toUri());
        return new ResponseEntity<>(createdProfile , headers, HttpStatus.CREATED);
    }
    
    //ProfileService create function that returns null in the test case
    public Profile create(User user) {
        Profile existing = repository.findByName(user.getUsername());
        Assert.isNull(existing, "profile already exists: " + user.getUsername());
    
        authClient.createUser(user); //Feign client request
    
        Profile profile = new Profile();
        profile.setName(user.getUsername());
        repository.save(profile);
    
        return profile;
    }
    
    // The test case
    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = ProfileApplication.class)
    @WebAppConfiguration
    public class ProfileControllerTest {
    
        @InjectMocks
        private ProfileController profileController;
    
        @Mock
        private ProfileService profileService;
    
        private MockMvc mockMvc;
    
        private static final ObjectMapper mapper = new ObjectMapper();
    
        private MediaType contentType = MediaType.APPLICATION_JSON;
    
        @Before
        public void setup() {
            initMocks(this);
            this.mockMvc = MockMvcBuilders.standaloneSetup(profileController).build();
        }
        @Test
        public void shouldCreateNewProfile() throws Exception {
    
            final User user = new User();
            user.setUsername("testuser");
            user.setPassword("password");
    
            String userJson = mapper.writeValueAsString(user);
    
            mockMvc.perform(post("/").contentType(contentType).content(userJson))
                    .andExpect(jsonPath("$.username").value(user.getUsername()))
                    .andExpect(status().isCreated());
    
        }
    }
    

    Tried to add when/thenReturn before post but still returns 409 response with null object.

    when(profileService.create(user)).thenReturn(profile);