Issue
I understand that JUnit 5 introduced substantial changes under the hood, however isnt't this supposed to be configured automatically?
build.gradle:
plugins {
id 'org.springframework.boot' version '2.2.2.RELEASE'
id 'io.spring.dependency-management' version '1.0.8.RELEASE'
id 'java'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
compile 'org.imgscalr:imgscalr-lib:4.2'
runtimeOnly 'com.h2database:h2'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
test {
useJUnitPlatform()
}
Repository, located in src/main/java/com/example/repositories:
import org.adventure.entities.Classified;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface ClassifiedRepository extends CrudRepository<Classified, Long> {}
Test, located in src/test/java/com/example/repositories:
import org.adventure.entities.Classified;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.assertTrue;
@DataJpaTest
public class ClassifiedRepositoryTest {
private TestEntityManager entityManager;
private ClassifiedRepository classifiedRepository;
public ClassifiedRepositoryTest(TestEntityManager entityManager, ClassifiedRepository classifiedRepository) {
this.entityManager = entityManager;
this.classifiedRepository = classifiedRepository;
}
@Test
public void classifiedCanBeFoundById() {
// GIVEN
Classified classified = new Classified("Cheap bike",
"Worn bike, used on a hobby level. Needs oiling", 300, "EUR");
entityManager.persist(classified);
entityManager.flush();
// WHEN
Optional<Classified> found = classifiedRepository.findById(classified.getId());
// THEN
assertTrue(found.isPresent());
}
}
Result: Too long to post here, please see here
Solution
There was a long discussion about this problem on github (https://github.com/spring-projects/spring-framework/issues/22286). You have three options:
- Add the annotation
@Autowired
on your constructor. By default, Spring does not make dependency injection in a contructor of a test class. You have to mention it.
@Autowired
public ClassifiedRepositoryTest(TestEntityManager entityManager, ClassifiedRepository classifiedRepository) {
this.entityManager = entityManager;
this.classifiedRepository = classifiedRepository;
}
- As discussed on github: Add
@TestConstructor(autowireMode = TestConstructor.AutowireMode.ALL)
at the top of your test class.
@TestConstructor(autowireMode = TestConstructor.AutowireMode.ALL)
@DataJpaTest
public class ClassifiedRepositoryTest { ... }
- Remove your constructor and annotate your fields with
@Autowired
.
@Autowired
private TestEntityManager entityManager;
@Autowired
private ClassifiedRepository classifiedRepository;
Answered By - RUARO Thibault
Answer Checked By - Timothy Miller (JavaFixing Admin)