황민욱
황민욱

Reputation: 53

can't find saved entity in test

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

Answers (1)

Maciej Kowalski
Maciej Kowalski

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

Related Questions