Reputation: 5749
I have a test class
@RunWith(SpringRunner.class)
@DataJpaTest
I have two tests. In every test I do the same operation, persist the object. Only the find call are different.
If I run both tests together they fail but if I run test one after another they are successful.
There is no reset between each test. How to do that? Only the call to the repository is different in each test.
@Test
public void findTopByCommerceCommerceIdOrderByEntryTimeDesc() {
Long commerceId = 1L;
Commerce commerce = new Commerce();
commerce.setName("test");
this.entityManager.persist(commerce);
Member member = new Member();
member.setCommerce(commerce);
member.setMan(true);
member.setName("bob binette");
this.entityManager.persist(member);
Visit visit1 = new Visit();
visit1.setCommerce(commerce);
visit1.setMember(member);
visit1.setEntryTime(LocalDateTime.of(LocalDate.now(), LocalTime.now()));
Visit visit2 = new Visit();
visit2.setCommerce(commerce);
visit2.setMember(member);
visit2.setEntryTime(LocalDateTime.of(LocalDate.now().minusDays(2), LocalTime.now()));
this.entityManager.persist(visit1);
this.entityManager.persist(visit2);
Visit visit = visitRepository.findTopByCommerceCommerceIdOrderByEntryTimeDesc(commerceId);
assertEquals(visit.getVisitId(), Long.valueOf("1"));
}
Edit
i put all the code : http://pastebin.com/M9w9hEYQ
Upvotes: 47
Views: 50677
Reputation: 191
Although this issue has been solved for you, I would just like to state that clearing the repository was not cutting for my particular use-case as I have an data.sql initialization for my h2 which creates a user by default, so I had to add an application.properties file under src/test/resources with the following property:
spring.datasource.initialization-mode=never
Reference to the thread that made that suggestion: Spring Boot ignore data.sql when running unit tests
Upvotes: 0
Reputation: 2203
Use the @Transactional(propagation = Propagation.REQUIRES_NEW)
on top of your test class, that will explicitly request, the creation of a new transaction after each method
Upvotes: 1
Reputation: 31
@DirtiesContext(classMode =DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD
)
works for me, but it is only necessary when I run @DataJpaTest()
with @AutoConfigureTestDatabase(replace=Replace.NONE)
and costum profile for mysql, default h2 works without this.
Upvotes: 0
Reputation: 301
Use @Sql with ExecutionPhase.AFTER_TEST_METHOD and pass the script that is to be used to clean the database
@Sql(scripts="classpath:cleanup.sql",executionPhase=Sql.ExecutionPhase.AFTER_TEST_METHOD)
@Test
public void whateverIsYourTestMethod()
{
...
}
In case you are using @Transactional annotation , you can use :
@Sql(scripts="classpath:cleanup.sql",executionPhase=Sql.ExecutionPhase.AFTER_TEST_METHOD,config = @SqlConfig
( transactionMode = TransactionMode.ISOLATED,
transactionManager = "transactionManager",
dataSource= "dataSource" ))
@Test
@Commit
@Transactional
public void whateverIsYourTestMethod(){...}
Upvotes: 6
Reputation: 609
Add the @DirtiesContext annotation, but provide it with the AFTER_EACH_TEST_METHOD classMode
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
Upvotes: 46
Reputation: 431
Have you try to clear the peristence cache between each tests, according to TestEntityManager#clear()
@After
public void clear() {
this.entityManager.clear();
}
Or maybe try to set your Visitor
as fields and remove them in an after, than flush the changes :
Visit visit1;
Visit visit2;
@After
public void clear(){
if (visit1 != null)
this.entityManager.remove(visit1);
if (visit2 != null)
this.entityManager.remove(visit2);
this.entityManager.flush();
}
Upvotes: 4
Reputation: 497
You can use @DirtiesContext annotation on your test class to reset the tests, there you can also choose when to reset. Default is after every method, but you can change that by passing in different parameters to the @DirtiesContext annotation.
import org.springframework.test.annotation.DirtiesContext;
@RunWith(SpringRunner.class)
@DataJpaTest
@DirtiesContext
public class VisitRepositoryTest {
Upvotes: 8
Reputation: 2146
In your case for each test you persist the same data. So you should persist data before all test or persist before each test and clean after it.
1. Persist before all test
@BeforeClass
public static void init(){
//persist your data
}
@AfterClass
public static void clear(){
//remove your data
}
@Test
public void findTopByCommerceCommerceIdOrderByEntryTimeDesc() {
Visit visit = visitRepository.findTopByCommerceCommerceIdOrderByEntryTimeDesc(commerceId);
assertEquals(visit.getVisitId(), Long.valueOf("1"));
}
In this case @AfterClass is optionally
2. Persist before each test and clean after each test
@Before
public void init(){
//persist your data
}
@After
public void clear(){
//remove your data
}
@Test
public void findTopByCommerceCommerceIdOrderByEntryTimeDesc() {
Visit visit = visitRepository.findTopByCommerceCommerceIdOrderByEntryTimeDesc(commerceId);
assertEquals(visit.getVisitId(), Long.valueOf("1"));
}
Remember that methods which use @BeforeClass and @AfterClass must be static.
Upvotes: 15