Issue
In my app, there is a controller, a service, a repo and a class. I am writing unit test to verify my PUT request. In postman, the put request works fine, however, when testing in JUnit test, it throws EmptyResultDataAccessException eror. Many other tests have the same problem and all of them require to find a specific entry in the repo by id. I think this is the problem. Please help me on this.
@Data
@Entity
public class ErrorMessage {
private @Id @GeneratedValue Long id;
private String message;
private int code;
public ErrorMessage() {
}
public ErrorMessage(int code, String message) {
this.code = code;
this.message = message;
}
}
@Repository
interface ErrorMessageRepository extends JpaRepository<ErrorMessage, Long> {
List<ErrorMessage> findByCode(int code);
}
@Service
public class ErrorMessageService {
@Autowired
ErrorMessageRepository repository;
@Transactional
public List<ErrorMessage> getAll()
{
return repository.findAll();
}
@Transactional(readOnly = true)
public Optional<ErrorMessage> getById(Long id)
{
return repository.findById(id);
}
@Transactional(readOnly = true)
public List<ErrorMessage> getByCode(int code)
{
return repository.findByCode(code);
}
@Transactional
public ErrorMessage saveOne(ErrorMessage messages)
{
return repository.save(messages);
}
@Transactional
public Optional<ErrorMessage> deleteById(long id)
{
Optional<ErrorMessage> em = repository.findById(id);
repository.deleteById(id);
return em;
}
@Transactional
public ErrorMessage updateById(long id, ErrorMessage newMessage)
{
ErrorMessage m = repository.findById(id).get();
m.setCode(newMessage.getCode());
m.setMessage(newMessage.getMessage());
repository.save(m);
return m;
}
}
class ErrorMessageController {
private static final Logger log = LoggerFactory.getLogger(ErrorMessageController.class);
@Autowired
ErrorMessageRepository repository;
@Autowired
private ErrorMessageService ems;
@GetMapping("/errormessages")
public List<ErrorMessage> getAll() {
return ems.getAll();
}
@GetMapping("/errormessagesbycode/{code}")
public List<ErrorMessage> getByCode(@PathVariable int code) {
return ems.getByCode(code);
}
@GetMapping("/errormessage/{id}")
ErrorMessage getById(@PathVariable Long id) {
return ems.getById(id)
.orElseThrow(() -> new MessageNotFoundException(id));
}
@PostMapping("/errormessage")
ErrorMessage newMessage(@RequestBody ErrorMessage newMessage) {
return ems.saveOne(newMessage);
}
@DeleteMapping("/errormessage/{id}")
Optional<ErrorMessage> deleteMessage(@PathVariable Long id) {
return ems.deleteById(id);
}
@PutMapping("/errormessage/{id}")
ErrorMessage updateMessage(@PathVariable Long id, @RequestBody ErrorMessage newMessage) {
return ems.updateById(id, newMessage);
}
}
@SpringBootTest
@AutoConfigureMockMvc
public class ErrorMessageTest {
private static ErrorMessage em, emId;
private static ObjectMapper mapper;
@Autowired
private MockMvc mockMvc;
@BeforeAll
public static void init() throws Exception {
mapper = new ObjectMapper();
em = new ErrorMessage(400, "bad request0");
emId = new ErrorMessage(400, "bad request0");
emId.setId(Long.valueOf(1));
}
@Test
void putMessage() throws Exception {
ErrorMessage modifiedMessage = new ErrorMessage(400, "modified");
this.mockMvc.perform(MockMvcRequestBuilders
.put("/errormessage/{id}", emId.getId())
.contentType(MediaType.APPLICATION_JSON)
.content(mapper.writeValueAsString(modifiedMessage)))
.andExpect(status().isOk())
.andExpect(content().string(mapper.writeValueAsString(modifiedMessage)));
}
}
Solution
I found out the bug. The order of the unit test is random. All i need to do is use @Order to ensure the order.
Answered By - Stephanie Liu