1

私のSpring構成では、ビューでセッションを開いたままにするように依頼しました。

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

ただし、この Bean は明らかに私の TestNG 単体テストをビューとは見なしません。;-) 大丈夫ですが、単体テスト中に恐ろしい LazyInitializationException を回避できるように、単体テスト用の同様の Bean はありますか? これまでのところ、私の単体テストの半分はそれが原因で死んでいます。

私の単体テストは通常​​次のようになります。

@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
  }



}

setUp() を次のように変更してみました:

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);
}

しかし、これは間違った方法だと思います。後でテストするためにトランザクションを台無しにします。OpenSessionInTestInterceptor のようなものはありますか、これを行うためのより良い方法はありますか、それともこれを行う方法ですか?その場合、私はそれについて何を誤解しましたか?

乾杯

ニック

4

2 に答える 2

6

私はテストに JUnit を使用しているため、次の例を TestNG に適合させる必要があります。個人的には、SpringJUnit4ClassRunner を使用して、基本テスト クラスでトランザクションをバインドします。

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

「@Before」では、RequestContextHolder に MockHttpServletRequest を挿入します。

@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);

     .......

マニュアルから情報を取得しました

于 2009-10-09T13:18:57.200 に答える
1

うーん..ここでは頭がいいわけではありませんが、それsetUp()は意図されたものではありません.

基本的な考え方は、テストを自己完結型で再入可能にすることです。つまり、特定のレコードを持つデータベースに依存したり、テストでデータベースを永続的に変更したりしないでください。したがって、プロセスは次のとおりです。

  1. で必要なレコードを作成します。setUp()
  2. 実際のテストを実行する
  3. クリーンアップ (必要な場合)tearDown()

(1)、それぞれ (2)、および (3) はすべて別々のトランザクションで実行されるため、LazyInitializationException で問題が発生します。mockEntity = myEntityService.read(1);setUp から実際のテストに移動すると、それはなくなります。個々のテストを直接補足するものではなく、テスト データを作成する必要がある場合は、setUp を使用してください。

于 2009-10-09T18:32:11.287 に答える