LazyInitializationException أثناء فئات كيان السبات في اختبار الوحدة للاستخدام في الربيع ، باستخدام TestNg
-
20-09-2019 - |
سؤال
في تكوين الربيع الخاص بي ، طلبت أن تظل الجلسة مفتوحة في آرائي:
<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()
كان المقصود ل.
الفكرة الأساسية هي أن تكون اختباراتك مكتفية ذاتيًا وإعادة إدخالها ، مما يعني أنك يجب ألا تعتمد على قاعدة البيانات التي لها سجلات معينة ولا ينبغي عليك تغيير قاعدة البيانات بشكل دائم في الاختبار. العملية ، وبالتالي ، هي:
- إنشاء أي سجلات ضرورية في
setUp()
- قم بتشغيل اختباراتك الفعلية
- تنظيف (إذا لزم الأمر) في
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);
.......
أخذت المعلومات من كتيب