私はe2eユースケースをテストするために、Spring Boot Testを使用して簡単な統合テストを実行しようとしています。リポジトリにデータを保存させることができないため、テストが機能しません。Springコンテキストに問題があると思います...
これは私のエンティティです:
@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Person {
@Id
private int id;
private String name;
}
これはPersonリポジトリです:
@Repository
public interface PersonRepository extends JpaRepository<Person, Integer> {
}
個人サービス:
@Service
public class PersonService {
@Autowired
private PersonRepository repository;
public Person createPerson(int id,String name) {
return repository.save(new Person(id, name));
}
public List<Person> getPersons() {
return repository.findAll();
}
}
パーソンコントローラー:
@RequestMapping
@RestController
public class PersonController {
@Autowired
private PersonService personService;
@RequestMapping("/persons")
public List<Person> getPersons() {
return personService.getPersons();
}
}
メインのアプリケーションクラス:
@SpringBootApplication
public class BootIntegrationTestApplication {
public static void main(String[] args) {
SpringApplication.run(BootIntegrationTestApplication.class, args);
}
}
Application.propertiesファイル:
spring.datasource.url= jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=password
spring.jpa.hibernate.ddl-auto=create
spring.jpa.show-sql=true
そしてテスト:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class BootIntegrationTestApplicationTests {
@Autowired
private PersonService personService;
@Autowired
private TestRestTemplate restTemplate;
@Test
@Transactional
public void contextLoads() {
Person person = personService.createPerson(1, "person1");
Assert.assertNotNull(person);
ResponseEntity<Person[]> persons = restTemplate.getForEntity("/persons", Person[].class);
}
}
サービスがPersonエンティティを保存していないため、テストは機能しません....よろしくお願いします
_@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
public class SmokeTest {
@Autowired
UserController userController;
@Autowired
UserDao userDAO;
@Rollback(false) // This is key to avoid rollback.
@Test
public void contextLoads() throws Exception {
System.out.println("Hiren");
System.out.println("started");
userDAO.save(new User("tyx", "[email protected]"));
}
}
_
ロールバックを回避するには、@Rollback(false)
が重要であることを参照してください。
M. Deinumのおかげで、ポイントはわかったと思います。テストのロジックを2つのテストに分離するのが最善です。
テスト1:
@Test
@Transactional
public void testServiceSaveAndRead() {
personService.createPerson(1, "person1");
Assert.assertTrue(personService.getPersons().size() == 1);
}
テスト2:
@MockBean
private PersonService personService;
@Before
public void setUp() {
//mock the service
given(personService.getPersons())
.willReturn(Collections.singletonList(new Person(1, "p1")));
}
@Test
public void testController() {
ResponseEntity<Person[]> persons = restTemplate.getForEntity("/persons", Person[].class);
Assert.assertTrue(persons.getBody()!=null && persons.getBody().length == 1);
}
それがいつか誰かを助けることを願っています...あなたのすべてに感謝します
DBトランザクションを作成する_@Test
_関数ごとに、変更を永続的に永続化する場合は、@Rollback(false)
を使用できます
_@Rollback(false)
@Test
public void createPerson() throws Exception {
int databaseSizeBeforeCreate = personRepository.findAll().size();
// Create the Person
restPersonMockMvc.perform(post("/api/people")
.contentType(TestUtil.APPLICATION_JSON_UTF8)
.content(TestUtil.convertObjectToJsonBytes(person)))
.andExpect(status().isCreated());
// Validate the Person in the database
List<Person> personList = personRepository.findAll();
assertThat(personList).hasSize(databaseSizeBeforeCreate + 1);
Person testPerson = personList.get(personList.size() - 1);
assertThat(testPerson.getFirstName()).isEqualTo(DEFAULT_FIRST_NAME);
assertThat(testPerson.getLastName()).isEqualTo(DEFAULT_LAST_NAME);
assertThat(testPerson.getAge()).isEqualTo(DEFAULT_AGE);
assertThat(testPerson.getCity()).isEqualTo(DEFAULT_CITY);
}
_
JHipsterによって生成されたSpringBootプロジェクトでテストしました。
@Rollback(false)
は使用しないでください。単体テストはデータを生成するべきではありません。
JPA FlushModeはAUTO
(デフォルト-クエリが発生したときにINSERT/UPDATE/DELETE SQLをフラッシュする)/ COMMIT
です。
FLUSHを強制するために、またはEntityManagerを使用して強制的にフラッシュするために、作業エンティティをクエリするだけです
@Test
public void testCreate(){
InvoiceRange range = service.createInvoiceRange(1, InvoiceRangeCreate.builder()
.form("01GTKT0/010")
.serial("NV/18E")
.effectiveDate(LocalDate.now())
.rangeFrom(1L)
.rangeTo(1000L)
.build(), new byte[] {1,2,3,4,5});
service.findByCriteria(1, "01GTKT0/010", "NV/18E"); // force flush
// em.flush(); // another way is using entityManager for force flush
}
エンティティを保存するためのSpringにはトランザクションが必要です。ただし、トランザクションがコミットされるまで、変更は別のトランザクションからは見えません。
最も簡単な方法は、トランザクションのコミット後にコントローラーを呼び出すことです
@Test
@Transactional
public void contextLoads() {
Person person = personService.createPerson(1, "person1");
Assert.assertNotNull(person);
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
@Override
public void afterCommit() {
ResponseEntity<Person[]> persons = restTemplate.getForEntity("/persons", Person[].class);
}
});
}