Reputation: 53
I'm testing my spring application, but there is wired thing. I can't find out why this happens.
in my spring code, I save requestBody into db using crudRepository. and I could find saved item with crudRepository. but when I run unittest and invoke same method with TestRestTemplate, I can't find saved item with crudRepository.
server
@PostMapping("")
public Question saveQuestion(@RequestBody Question question) {
questionRepository.save(question);
for(Question _p:questionRepository.findAll()) {
Application.LOG.info("[saveQuestion] "+_p.toString());
}
// I can find saved Question
return question;
}
unittest
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Transactional
public class QuestionControllerTest {
@Autowired TestRestTemplate restTemplate;
@Autowired QuestionRepository questionRepository;
@Test
public void addNewQuestionTest() throws InterruptedException {
String json= "{\"uniqueId\":1}";
HttpEntity<String> req = new HttpEntity<>(json, headers);
ResponseEntity<Question> response = restTemplate.postForEntity("/question", req, Question.class);
for(Question _p:questionRepository.findAll()) {
Application.LOG.info("[addNewQuestion]"+_p.toString());
}
// I can't find saved question.
}
}
log looks like this.
[saveQuestion] Question(0)
[saveQuestion] Question(1)
[addNewQuestionTest] Question(0)
but I excepted
[saveQuestion] Question(0)
[saveQuestion] Question(1)
[addNewQuestionTest] Question(0)
[addNewQuestionTest] Question(1)
I checked db has data and saveQuestion method prints 2 items. but there is only 1 item in addNewQuestionTest method.
Am I missing something?
Upvotes: 5
Views: 2219
Reputation: 26532
This is just an assumption but might be happening here is a follows:
1) You have marked the entire test to be run under a certain transaction:
@Transactional
public class QuestionControllerTest {
2) When you hit the post method, it saves the entity but within its own / new transaction
ResponseEntity<Question> response = restTemplate.postForEntity("/question", req, Question.class);
The transaction from 1) is still active here, so you have 2 transactions.
3) As the save has been performed in a separate transaction while the first one is still active, the first one does not yet access to the data saved by transaction 2).
Solution
As Spring JPA repositories are Transactional by nature i would remove the @Transactional
from the test configuration.
Now, when you hit the questionRepository.findAll()
, it would triggered a new transaction which would have access to the data saved by the first transaction persisting the questionarre.
Upvotes: 6