Issue
I'm pretty new to Spring Boot and JUnit, so im trying to build a Rest API with validation contraints like below:
Entity class:
@Entity
public class CareerLevel {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer careerLevelId;
@NotNull
@NotEmpty
@Size(max = 50)
private String careerLevel;
// Getters and Setters
}
Controller:
@PostMapping
public ResponseEntity<CareerLevel> postCareerLevel(@RequestBody @Valid CareerLevel careerLevel) {
// saving data
CareerLevel body = careerLevelRepository.save(careerLevel);
return ResponseEntity.status(201).body(body);
}
When I test post method on Insomnia (or any other HTTP client) with invalid values (null, too long strings, etc) It's returning Bad Request (exactly how I expected). But when I run my Test class, It's throwing an exception called TransactionSystemException
Test Method:
@Test
void testPostCareerLevelInvalidValues() {
CareerLevel careerLevel = new CareerLevel();
careerLevel.setCareerLevel("tooLongStriiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiing");
ResponseEntity<CareerLevel> response1 = controller.postCareerLevel(careerLevel); // throwing TransactionSystemException
assertEquals(400, response1.getStatusCode().value());
}
How can I handle that exception and get response data?
Solution
Hi I tried your code locally and added a lombok annotation to create a builder for entity.
see @Builder
I recommend using MockMvc
when testing your Controller class.
I also used mockito to mock CareerLevelRepository
and injected it into CareerLevelController
@ExtendWith(MockitoExtension.class)
class CareerLevelControllerTest {
@Mock
private CareerLevelRepository careerLevelRepository;
@InjectMocks
private CareerLevelController careerLevelController;
private MockMvc mockMvc;
@BeforeEach
void setUp() {
mockMvc = MockMvcBuilders.standaloneSetup(careerLevelController)
.build();
}
private final ObjectMapper objectMapper = new ObjectMapper();
@Test
void testPostCareerLevelInvalidValues() throws Exception {
CareerLevel request = CareerLevel.builder()
.careerLevel("tooLongStriiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiing")
.build();
this.mockMvc
.perform(post("/career-levels").contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(request)))
.andExpect(status().is(400));
}
}
It simply uses MockMvc to create a request rather than calling the method. ObjectMapper
converts our created request
to Json which has been sent as body.
Answered By - mbehram
Answer Checked By - Dawn Plyler (JavaFixing Volunteer)