LazyInitializationException أثناء فئات كيان السبات في اختبار الوحدة للاستخدام في الربيع ، باستخدام TestNg

StackOverflow https://stackoverflow.com/questions/1543515

سؤال

في تكوين الربيع الخاص بي ، طلبت أن تظل الجلسة مفتوحة في آرائي:

  <bean name="openSessionInViewInterceptor" class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
    <property name="sessionFactory" ref="sessionFactory"/>
    <property name="flushMode" value="0" />
  </bean> 

ومع ذلك ، فإن هذه الفاصوليا لا تعتبر اختبارات وحدة testng الخاصة بي بمثابة عرض. ؛-) هذا كل شيء على ما يرام ، ولكن هل هناك حبة مماثلة لاختبارات الوحدة بحيث أتجنب الإفصاح البطيء المخيف أثناء اختبار الوحدة؟ حتى الآن ، يموت نصف اختبارات وحدتي بسبب ذلك.

يبدو اختبار الوحدة الخاص بي مثل هذا:

@ContextConfiguration({"/applicationContext.xml", "/applicationContext-test.xml"})
public class EntityUnitTest extends AbstractTransactionalTestNGSpringContextTests {

  @BeforeClass
  protected void setUp() throws Exception {
    mockEntity = myEntityService.read(1);
  }

  /* tests */

  @Test
  public void LazyOneToManySet() {
    Set<SomeEntity> entities = mockEntity.getSomeEntitySet();
    Assert.assertTrue(entities.size() > 0); // This generates a LazyInitializationException
  }



}

لقد حاولت تغيير الإعداد () إلى هذا:

private SessionFactory sessionFactory = null;

@BeforeClass
protected void setUp() throws Exception {
  sessionFactory = (SessionFactory) this.applicationContext.getBean("sessionFactory");
  Session s = sessionFactory.openSession();
  TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(s));

  mockEntity = myEntityService.read(1);
}

لكنني أعتقد أن هذه هي الطريقة الخاطئة للقيام بذلك ، وأفسد المعاملة للاختبارات اللاحقة. هل هناك شيء مثل مفترح epensessionIntestOptor ، هل هناك طرق أفضل للقيام بذلك ، أم أن هذه هي الطريقة للقيام بذلك ، وفي هذه الحالة ما الذي أسيء فهمه بشأنه؟

هتافات

نيك

هل كانت مفيدة؟

المحلول

أم .. ألا تكون ذكيًا هنا ، لكن هذا ليس ما setUp() كان المقصود ل.

الفكرة الأساسية هي أن تكون اختباراتك مكتفية ذاتيًا وإعادة إدخالها ، مما يعني أنك يجب ألا تعتمد على قاعدة البيانات التي لها سجلات معينة ولا ينبغي عليك تغيير قاعدة البيانات بشكل دائم في الاختبار. العملية ، وبالتالي ، هي:

  1. إنشاء أي سجلات ضرورية في setUp()
  2. قم بتشغيل اختباراتك الفعلية
  3. تنظيف (إذا لزم الأمر) في tearDown()

(1) ، كل (2) ، و (3) جميعها تعمل في معاملات منفصلة - وبالتالي المشكلة التي تحصل عليها مع LazyinitializationException. يتحرك mockEntity = myEntityService.read(1); من الإعداد إلى الاختبار (الاختبارات) الفعلية وسوف يختفي ؛ استخدم الإعداد إذا كنت بحاجة إلى إنشاء بعض بيانات الاختبار ، وليس كملحق مباشر للاختبار الفردي.

نصائح أخرى

أنا أستخدم Junit للاختبارات الخاصة بي ، لذلك تحتاج إلى تكييف المثال التالي مع testng. personnaly أنا أستخدم springjunit4classrunner لربط المعاملات في فئة اختبار قاعدة:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:/applicationContext-struts.xml")
@TransactionConfiguration(transactionManager = "transactionManager")
@Transactional
public abstract class BaseTests {

وفي "before" ، حقن mockhttpservletrequest في requestContextholder:

@Before
public void prepareTestInstance() throws Exception {
    applicationContext.getBeanFactory().registerScope("session", new SessionScope());
    applicationContext.getBeanFactory().registerScope("request", new RequestScope());
    MockHttpServletRequest request = new MockHttpServletRequest();

    ServletRequestAttributes attributes = new ServletRequestAttributes(request);
    RequestContextHolder.setRequestAttributes(attributes);

     .......

أخذت المعلومات من كتيب

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top