จะทดสอบที่เก็บข้อมูล Spring ได้อย่างไร


142

ฉันต้องการพื้นที่เก็บข้อมูล (พูดUserRepository) ที่สร้างขึ้นด้วยความช่วยเหลือของ Spring Data ฉันยังใหม่กับ Spring-data (แต่ไม่ใช่ฤดูใบไม้ผลิ) และฉันใช้บทช่วยสอนนี้ ตัวเลือกของเทคโนโลยีสำหรับจัดการกับฐานข้อมูลคือ JPA 2.1 และ Hibernate ปัญหาคือฉันไม่รู้วิธีเขียนการทดสอบหน่วยสำหรับที่เก็บดังกล่าว

ลองใช้create()วิธีการเช่น ในขณะที่ฉันกำลังทำการทดสอบก่อนฉันควรจะเขียนการทดสอบหน่วยสำหรับมัน - และนั่นคือสิ่งที่ฉันพบปัญหาสามประการ:

  • ขั้นแรกฉันจะฉีดเลียนแบบEntityManagerการใช้งานUserRepositoryอินเทอร์เฟซที่ไม่มีอยู่ได้อย่างไร Spring Data จะสร้างการใช้งานตามอินเทอร์เฟซนี้:

    public interface UserRepository extends CrudRepository<User, Long> {}
    

    อย่างไรก็ตามฉันไม่รู้ว่าจะบังคับให้ใช้การEntityManagerจำลองและการล้อเลียนอื่น ๆ อย่างไร - ถ้าฉันเขียนการใช้งานด้วยตัวเองฉันอาจมีวิธีการตั้งค่าเพื่อEntityManagerให้ฉันใช้การจำลองสำหรับการทดสอบหน่วย (ในฐานะที่เป็นสำหรับการเชื่อมต่อฐานข้อมูลจริงฉันมีJpaConfigurationระดับกำกับด้วย@Configurationและ@EnableJpaRepositoriesที่โปรแกรมกำหนดถั่วDataSource, EntityManagerFactory, EntityManagerฯลฯ - แต่ที่เก็บควรจะทดสอบที่เป็นมิตรและอนุญาตให้มีการเอาชนะสิ่งเหล่านี้)

  • ประการที่สองฉันควรทดสอบการโต้ตอบหรือไม่? มันยากสำหรับฉันที่จะเข้าใจว่าวิธีการใดEntityManagerและQueryควรจะเรียกว่าอะไร (คล้าย ๆ กันverify(entityManager).createNamedQuery(anyString()).getResultList();) เนื่องจากฉันไม่ใช่คนที่เขียนการนำไปใช้

  • ประการที่สามฉันควรจะทดสอบหน่วยวิธีการสร้างข้อมูลโดยสปริงตั้งแต่แรกหรือไม่? ดังที่ฉันทราบรหัสไลบรารีของบุคคลที่สามไม่ควรผ่านการทดสอบหน่วย - เฉพาะโค้ดที่นักพัฒนาเขียนขึ้นเองเท่านั้นที่ควรได้รับการทดสอบหน่วย แต่ถ้าเป็นเรื่องจริงก็ยังคงนำคำถามแรกกลับมาที่เกิดเหตุ: พูดว่าฉันมีวิธีการที่กำหนดเองสองสามวิธีสำหรับที่เก็บของฉันซึ่งฉันจะเขียนการนำไปใช้ฉันจะฉีดล้อเลียนของฉันEntityManagerและQueryในขั้นสุดท้ายสร้างได้อย่างไร ที่เก็บ?

หมายเหตุ: ฉันจะทดสอบการขับที่เก็บของฉันโดยใช้ทั้งการรวมและการทดสอบหน่วย สำหรับการทดสอบการรวมของฉันฉันใช้ฐานข้อมูลในหน่วยความจำ HSQL และเห็นได้ชัดว่าฉันไม่ได้ใช้ฐานข้อมูลสำหรับการทดสอบหน่วย

และอาจเป็นคำถามที่สี่การทดสอบการสร้างกราฟวัตถุและการดึงกราฟวัตถุที่ถูกต้องในการทดสอบการรวม (พูดว่าฉันมีกราฟวัตถุที่ซับซ้อนที่กำหนดด้วยไฮเบอร์เนต) หรือไม่

อัปเดต: วันนี้ฉันได้ทดลองใช้การฉีดจำลองอย่างต่อเนื่อง - ฉันได้สร้างคลาสชั้นในแบบคงที่เพื่อให้สามารถฉีดจำลองได้

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@Transactional
@TransactionConfiguration(defaultRollback = true)
public class UserRepositoryTest {

@Configuration
@EnableJpaRepositories(basePackages = "com.anything.repository")
static class TestConfiguration {

    @Bean
    public EntityManagerFactory entityManagerFactory() {
        return mock(EntityManagerFactory.class);
    }

    @Bean
    public EntityManager entityManager() {
        EntityManager entityManagerMock = mock(EntityManager.class);
        //when(entityManagerMock.getMetamodel()).thenReturn(mock(Metamodel.class));
        when(entityManagerMock.getMetamodel()).thenReturn(mock(MetamodelImpl.class));
        return entityManagerMock;
    }

    @Bean
    public PlatformTransactionManager transactionManager() {
        return mock(JpaTransactionManager.class);
    }

}

@Autowired
private UserRepository userRepository;

@Autowired
private EntityManager entityManager;

@Test
public void shouldSaveUser() {
    User user = new UserBuilder().build();
    userRepository.save(user);
    verify(entityManager.createNamedQuery(anyString()).executeUpdate());
}

}

อย่างไรก็ตามการเรียกใช้การทดสอบนี้ทำให้ฉันมี stacktrace ต่อไปนี้:

java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:99)
at org.springframework.test.context.DefaultTestContext.getApplicationContext(DefaultTestContext.java:101)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:319)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:212)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:232)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:175)
at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:77)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:195)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:63)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRepository': Error setting property values; nested exception is org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:
PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'entityManager' threw exception; nested exception is java.lang.IllegalArgumentException: JPA Metamodel must not be null!
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1493)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1197)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:684)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
    at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:121)
    at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)
    at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:100)
    at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:250)
    at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContextInternal(CacheAwareContextLoaderDelegate.java:64)
    at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:91)
    ... 28 more
Caused by: org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:
PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'entityManager' threw exception; nested exception is java.lang.IllegalArgumentException: JPA Metamodel must not be null!
    at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:108)
    at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:62)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1489)
    ... 44 more

คำตอบ:


123

tl; dr

เพื่อให้สั้น - ไม่มีวิธีการทดสอบหน่วยเก็บข้อมูล Spring Data JPA อย่างสมเหตุสมผลด้วยเหตุผลง่ายๆนั่นคือวิธีที่ยุ่งยากในการล้อเลียนทุกส่วนของ JPA API ที่เราเรียกร้องให้บูตสแตรปที่เก็บ การทดสอบหน่วยไม่สมเหตุสมผลที่นี่เนื่องจากคุณมักจะไม่เขียนโค้ดการใช้งานด้วยตัวเอง (ดูย่อหน้าด้านล่างเกี่ยวกับการใช้งานแบบกำหนดเอง) ดังนั้นการทดสอบการรวมจึงเป็นแนวทางที่เหมาะสมที่สุด

รายละเอียด

เราทำการตรวจสอบและตั้งค่าล่วงหน้าค่อนข้างมากเพื่อให้แน่ใจว่าคุณสามารถบูตได้เฉพาะแอปที่ไม่มีการสืบค้นที่ได้มาที่ไม่ถูกต้องเป็นต้น

  • เราสร้างและแคชCriteriaQueryอินสแตนซ์สำหรับเคียวรีที่ได้รับเพื่อให้แน่ใจว่าวิธีการสืบค้นไม่มีการพิมพ์ผิด สิ่งนี้ต้องการการทำงานกับ Criteria API และ meta.model
  • เราตรวจสอบคำค้นหาที่กำหนดด้วยตนเองโดยขอEntityManagerให้สร้างQueryอินสแตนซ์สำหรับสิ่งเหล่านั้น (ซึ่งจะทำให้เกิดการตรวจสอบความถูกต้องของไวยากรณ์การสืบค้นอย่างมีประสิทธิภาพ)
  • เราตรวจสอบMetamodelข้อมูลเมตาเกี่ยวกับประเภทโดเมนที่จัดการเพื่อเตรียมการตรวจสอบใหม่เป็นต้น

ทุกสิ่งที่คุณอาจเลื่อนออกไปในที่เก็บที่เขียนด้วยมือซึ่งอาจทำให้แอปพลิเคชันหยุดทำงานขณะรันไทม์ (เนื่องจากการสืบค้นที่ไม่ถูกต้องเป็นต้น)

หากคุณลองคิดดูไม่มีโค้ดที่คุณเขียนสำหรับที่เก็บของคุณจึงไม่จำเป็นต้องเขียนการทดสอบหน่วยใด ๆ คุณไม่จำเป็นต้องพึ่งพาฐานทดสอบของเราในการตรวจจับข้อบกพร่องพื้นฐาน (หากคุณยังคงพบจุดบกพร่องอยู่อย่าลังเลที่จะเพิ่มตั๋ว ) อย่างไรก็ตามจำเป็นต้องมีการทดสอบการผสานรวมอย่างแน่นอนเพื่อทดสอบสองด้านของเลเยอร์การคงอยู่ของคุณเนื่องจากเป็นลักษณะที่เกี่ยวข้องกับโดเมนของคุณ:

  • การแมปเอนทิตี
  • ความหมายของแบบสอบถาม (มีการตรวจสอบไวยากรณ์ในการพยายามบูตแต่ละครั้ง)

การทดสอบการบูรณาการ

โดยปกติจะทำได้โดยใช้ฐานข้อมูลในหน่วยความจำและกรณีทดสอบที่บูตสปริงApplicationContextโดยปกติผ่านกรอบบริบททดสอบ (ตามที่คุณทำอยู่แล้ว) เติมข้อมูลฐานข้อมูลล่วงหน้า (โดยการแทรกอินสแตนซ์วัตถุผ่านEntityManagerหรือ repo หรือผ่านทางธรรมดา SQL) จากนั้นเรียกใช้วิธีการสืบค้นเพื่อตรวจสอบผลลัพธ์ของพวกเขา

ทดสอบการใช้งานแบบกำหนดเอง

ส่วนการนำไปใช้งานที่กำหนดเองของที่เก็บเขียนในลักษณะที่พวกเขาไม่จำเป็นต้องรู้เกี่ยวกับ Spring Data JPA เป็นถั่วฝักยาวธรรมดาที่ได้รับการEntityManagerฉีด คุณอาจแน่นอนอยากจะพยายามที่จะเยาะเย้ยปฏิสัมพันธ์กับมัน แต่จะซื่อสัตย์, หน่วยทดสอบ JPA ไม่ได้รับประสบการณ์ที่น่ารื่นรมย์เกินไปสำหรับเราเช่นเดียวกับการทำงานร่วมกับค่อนข้างมากของ indirections (ที่EntityManager-> CriteriaBuilder, CriteriaQueryฯลฯ ) ดังนั้น ที่คุณจบลงด้วยการล้อเลียนที่กลับมาล้อเลียนเป็นต้น


5
คุณมีลิงค์ไปยังตัวอย่างเล็ก ๆ ของการทดสอบการรวมกับฐานข้อมูลในหน่วยความจำ (เช่น h2) หรือไม่?
Wim Deblauwe

7
ตัวอย่างที่นี่ใช้ HSQLDB การเปลี่ยนไปใช้ H2 นั้นเป็นเรื่องของการแลกเปลี่ยนการพึ่งพาในไฟล์pom.xml.
Oliver Drotbohm

3
ขอบคุณ แต่ฉันหวังว่าจะได้เห็นตัวอย่างที่เติมฐานข้อมูลล่วงหน้าและ / หรือตรวจสอบฐานข้อมูลจริงๆ
Wim Deblauwe

1
ลิงก์ที่อยู่เบื้องหลัง "เขียนในลักษณะ" ใช้งานไม่ได้อีกต่อไป บางทีคุณสามารถอัปเดตได้?
Wim Deblauwe

1
ดังนั้นคุณเสนอให้ใช้การทดสอบการรวมแทนการทดสอบหน่วยสำหรับการใช้งานแบบกำหนดเองด้วยหรือไม่? แล้วไม่เขียน unit test ให้เลยเหรอ? เพียงเพื่อชี้แจง ก็โอเคถ้าใช่ ฉันเข้าใจเหตุผล (ซับซ้อนเกินกว่าจะล้อเลียนทุกเรื่อง) ฉันยังใหม่กับการทดสอบ JPA ดังนั้นฉันแค่อยากรู้
Ruslan Stelmachenko

52

ด้วย Spring Boot + Spring Data มันกลายเป็นเรื่องง่ายมาก:

@RunWith(SpringRunner.class)
@DataJpaTest
public class MyRepositoryTest {

    @Autowired
    MyRepository subject;

    @Test
    public void myTest() throws Exception {
        subject.save(new MyEntity());
    }
}

โซลูชันโดย @heez นำเสนอบริบททั้งหมดซึ่งจะแสดงเฉพาะสิ่งที่จำเป็นสำหรับการทำธุรกรรม JPA + เท่านั้น โปรดทราบว่าโซลูชันข้างต้นจะแสดงฐานข้อมูลในการทดสอบหน่วยความจำเนื่องจากสามารถพบได้ใน classpath


9
นี่คือการทดสอบการบูรณาการไม่ใช่การทดสอบหน่วยที่ OP กล่าวถึง
Iwo Kucharski

17
@IwoKucharski. คุณพูดถูกเกี่ยวกับคำศัพท์ อย่างไรก็ตาม: เนื่องจาก Spring Data ใช้อินเทอร์เฟซสำหรับคุณคุณจึงกดใช้ Spring ได้ยากและเมื่อถึงจุดนั้นจะกลายเป็นการทดสอบการผสานรวม หากฉันถามคำถามเช่นนี้ฉันอาจขอให้ทดสอบหน่วยโดยไม่ต้องคำนึงถึงคำศัพท์ ดังนั้นฉันจึงไม่เห็นว่าเป็นประเด็นหลักหรือแม้แต่ศูนย์กลางของคำถาม
Markus T

1
@RunWith(SpringRuner.class)ตอนนี้รวมอยู่ในไฟล์@DataJpaTest.
Maroun

@IwoKucharski ทำไมถึงเป็นการทดสอบการบูรณาการไม่ใช่การทดสอบหน่วย?
user1182625

@ user1182625 @RunWith(SpringRunner.classเริ่มบริบทสปริงซึ่งหมายความว่ากำลังตรวจสอบการรวมระหว่างหน่วยต่างๆ การทดสอบหน่วยเป็นการทดสอบหน่วยเดียว -> ชั้นเดียว จากนั้นคุณก็เขียนMyClass sut = new MyClass();และทดสอบ sut object (sut = service under test)
Iwo Kucharski

23

อาจจะมาช้าไปหน่อย แต่ฉันได้เขียนบางอย่างเพื่อจุดประสงค์นี้ ไลบรารีของฉันจะล้อเลียนวิธีการจัดเก็บ crud พื้นฐานสำหรับคุณรวมทั้งตีความฟังก์ชันส่วนใหญ่ของวิธีการสืบค้นของคุณ คุณจะต้องฉีดฟังก์ชั่นการใช้งานสำหรับแบบสอบถามดั้งเดิมของคุณเอง แต่ส่วนที่เหลือจะทำเพื่อคุณ

ลองดูสิ:

https://github.com/mmnaseri/spring-data-mock

อัปเดต

ตอนนี้อยู่ในใจกลาง Maven และอยู่ในสภาพที่ดีทีเดียว


16

หากคุณใช้ Spring Boot คุณสามารถใช้@SpringBootTestเพื่อโหลดApplicationContext(ซึ่งเป็นสิ่งที่ stacktrace ของคุณเห่าใส่คุณ) สิ่งนี้ช่วยให้คุณสามารถกำหนดเส้นทางอัตโนมัติในที่เก็บข้อมูลสปริงของคุณ อย่าลืมเพิ่ม@RunWith(SpringRunner.class)เพื่อเลือกคำอธิบายประกอบเฉพาะฤดูใบไม้ผลิ:

@RunWith(SpringRunner.class)
@SpringBootTest
public class OrphanManagementTest {

  @Autowired
  private UserRepository userRepository;

  @Test
  public void saveTest() {
    User user = new User("Tom");
    userRepository.save(user);
    Assert.assertNotNull(userRepository.findOne("Tom"));
  }
}

คุณสามารถอ่านเพิ่มเติมเกี่ยวกับการทดสอบในการบูตในฤดูใบไม้ผลิของพวกเขาเอกสาร


นี่เป็นตัวอย่างที่ค่อนข้างดี แต่ในมุมมองของฉันเข้าใจง่าย มีสถานการณ์ใดบ้างที่การทดสอบนี้อาจล้มเหลว?
HopeKing

ไม่ใช่ตัวนี้ต่อ แต่สมมติว่าคุณต้องการทดสอบPredicates (ซึ่งเป็นกรณีการใช้งานของฉัน) มันใช้งานได้ดีทีเดียว
heez

1
สำหรับฉันที่เก็บเป็นโมฆะเสมอ ความช่วยเหลือใด ๆ
Atul Chaudhary

นี่คือคำตอบที่ดีที่สุด ด้วยวิธีนี้คุณจะทดสอบ CrudRepo เอนทิตีและสคริปต์ DDL ซึ่งสร้างตารางของเอนทิตี
MirandaVeracruzDeLaHoyaCardina

ฉันได้เขียนแบบทดสอบนี้แล้ว ทำงานได้อย่างสมบูรณ์เมื่อการใช้ Repository ใช้ jdbcTemplate อย่างไรก็ตามเมื่อฉันเปลี่ยนการนำไปใช้สำหรับ spring-data (โดยการขยายอินเตอร์เฟสจาก Repository) การทดสอบล้มเหลวและ userRepository.findOne จะคืนค่า null มีแนวคิดในการแก้ปัญหานี้อย่างไร?
Rega

9

ในเวอร์ชันล่าสุดของ spring boot 2.1.1.RELEASEทำได้ง่ายๆดังนี้:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = SampleApplication.class)
public class CustomerRepositoryIntegrationTest {

    @Autowired
    CustomerRepository repository;

    @Test
    public void myTest() throws Exception {

        Customer customer = new Customer();
        customer.setId(100l);
        customer.setFirstName("John");
        customer.setLastName("Wick");

        repository.save(customer);

        List<?> queryResult = repository.findByLastName("Wick");

        assertFalse(queryResult.isEmpty());
        assertNotNull(queryResult.get(0));
    }
}

รหัสที่สมบูรณ์:

https://github.com/jrichardsz/spring-boot-templates/blob/master/003-hql-database-with-integration-test/src/test/java/test/CustomerRepositoryIntegrationTest.java


3
นี่เป็น 'ตัวอย่าง' ที่ค่อนข้างไม่สมบูรณ์: ไม่สามารถสร้างได้การทดสอบ "การรวม" จะใช้การกำหนดค่าเดียวกันกับรหัสการผลิต ได้แก่ . ไม่มีอะไรดีเลย
Martin Mucha

ฉันขอโทษ. ฉันจะแส้ฉันเพราะข้อผิดพลาดนี้ โปรดลองอีกครั้ง!
JRichardsz

สิ่งนี้ใช้ได้กับ2.0.0.RELEASESpring Boot
Nital

คุณควรใช้ฐานข้อมูลแบบฝังในการทดสอบนี้
TuGordoBello

7

เมื่อคุณต้องการเขียน i-test สำหรับที่เก็บข้อมูลแบบสปริงคุณสามารถทำได้ดังนี้:

@RunWith(SpringRunner.class)
@DataJpaTest
@EnableJpaRepositories(basePackageClasses = WebBookingRepository.class)
@EntityScan(basePackageClasses = WebBooking.class)
public class WebBookingRepositoryIntegrationTest {

    @Autowired
    private WebBookingRepository repository;

    @Test
    public void testSaveAndFindAll() {
        WebBooking webBooking = new WebBooking();
        webBooking.setUuid("some uuid");
        webBooking.setItems(Arrays.asList(new WebBookingItem()));
        repository.save(webBooking);

        Iterable<WebBooking> findAll = repository.findAll();

        assertThat(findAll).hasSize(1);
        webBooking.setId(1L);
        assertThat(findAll).containsOnly(webBooking);
    }
}

ในการทำตามตัวอย่างนี้คุณต้องใช้การอ้างอิงเหล่านี้:

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>1.4.197</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.assertj</groupId>
    <artifactId>assertj-core</artifactId>
    <version>3.9.1</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

5

ฉันแก้ไขสิ่งนี้โดยใช้วิธีนี้ -

    @RunWith(SpringRunner.class)
    @EnableJpaRepositories(basePackages={"com.path.repositories"})
    @EntityScan(basePackages={"com.model"})
    @TestPropertySource("classpath:application.properties")
    @ContextConfiguration(classes = {ApiTestConfig.class,SaveActionsServiceImpl.class})
    public class SaveCriticalProcedureTest {

        @Autowired
        private SaveActionsService saveActionsService;
        .......
        .......
}

4

ด้วย JUnit5 และ@DataJpaTestการทดสอบจะมีลักษณะดังนี้ (รหัส kotlin):

@DataJpaTest
@ExtendWith(value = [SpringExtension::class])
class ActivityJpaTest {

    @Autowired
    lateinit var entityManager: TestEntityManager

    @Autowired
    lateinit var myEntityRepository: MyEntityRepository

    @Test
    fun shouldSaveEntity() {
        // when
        val savedEntity = myEntityRepository.save(MyEntity(1, "test")

        // then 
        Assertions.assertNotNull(entityManager.find(MyEntity::class.java, savedEntity.id))
    }
}

คุณสามารถใช้TestEntityManagerจากorg.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManagerแพ็คเกจเพื่อตรวจสอบสถานะเอนทิตี


สปริงที่ดีกว่าเสมอในการสร้าง Id สำหรับเอนทิตี bean
Arundev

สำหรับ Java บรรทัดที่สองคือ @ExtendWith (value = SpringExtension.class)
Oozeerally
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.