0

JUnit テストで、Spring DAO の hibernate テンプレートを変更したいと考えています。このDAOは

  1. @Transactional で注釈が付けられているため、実行時にラップされ、
  2. Mockitos の spy() メソッドによってスパイされました。そのため、DAO はそのスパイによって 2 回ラップされます。

したがって、DAO には 2 つのラッピング オブジェクトがあります。1 つは @Transactional から、もう 1 つはスパイからです。これらのラッパーのどれが最初に作成されるかがわからないため、リフレクションを介して DAO で休止状態のテンプレートを設定できません。

二重ラップされた DAO でテンプレートを設定するにはどうすればよいですか?

[編集]

いくつかのソース:

/**
* This class gets wrapped by a proxy object because of @Transactional.
*/
@Transactional 
public class MyDao implements SomeDaoInterface { ... }

テストクラスで:

public class MyTestClass {
@Autowired 
private MyDao myDao;

@Test
public void myTestMethod() throws Exception {
   final MyDao daoSpy = spy(myDao);   // Dao gets wrapped with second wrapper

   final Field field = MyDao.class.getDeclaredField("template");
   field.setAccessible(true);
   field.set(daoSpy, mySpecialMockedTemplate);  // ERROR: want to inject the template but
                                                // dont know in which wrapper
}
}
4

2 に答える 2

2

フィールドにアクセスする代わりに、setter メソッドを呼び出します。

于 2011-11-04T15:28:13.417 に答える
2

リフレクション コードが間違っているようです。代わりに次のステートメントを使用してください。

field.set(daoSpy, mySpecialMockedTemplate);

ただし、テスト コードを見ると、Spring を使用してMyDaoインスタンスを作成しているようです。リフレクションを使用してテンプレートを設定するのはちょっと奇妙に思えますが、Spring で設定してみませんか? または、実際のセッターを使用しますか? または、フィールドを保護して、単体テストのみがアクセスできるようにします。

編集: インジェクションについては、テストで DAO インスタンスを作成し、specialMockedTemplateMockito でインジェクトすることができます。次のように書くことができます:

@RunWith(MockitoJUnitRunner.class)
public class MyTestClass {
    @InjectMocks private MyDao dao;

    @Mock SpecialTemplate specialTemplate;

    @Test void dao_should_call_the_template_with_parameter_A_and_B() {
        // given

        // when
        dao.someCall("A", "B");

        // then
        verify(specialTemplate).someCallWith("A", "B");
    }
}

ただし、いくつかの警告がありますが、可能であれば部分的なモックは避けてください (スパイを使用)。所有していない型をモークすることは避けてください。なぜこれが悪い考えなのか、このブログ記事のエントリを読む必要があります。

于 2011-11-04T15:53:58.153 に答える