19

Spring コンテキストには状態を持つ複数の Bean があるため、単体テストの前後にその状態をリセットしたいと思います。

私のアイデアは、Spring コンテキスト内のすべての Bean を通過するヘルパー クラスにメソッドを追加し、@Beforeorで注釈が付けられたメソッドをチェックし@Afterてそれらを呼び出すことでした。

からインスタンス化された Beanのリストを取得するにはどうすればよいApplicationContextですか?

注:定義されたすべてのBeanを単純に反復するソリューションは役に立ちません。多くの遅延Beanがあり、それらのいくつかはインスタンス化してはならないためですjava.sql.DataSource。その Bean は必要ありません)。

4

6 に答える 6

22

例えば:

 public static List<Object> getInstantiatedSigletons(ApplicationContext ctx) {
            List<Object> singletons = new ArrayList<Object>();

            String[] all = ctx.getBeanDefinitionNames();

            ConfigurableListableBeanFactory clbf = ((AbstractApplicationContext) ctx).getBeanFactory();
            for (String name : all) {
                Object s = clbf.getSingleton(name);
                if (s != null)
                    singletons.add(s);
            }

            return singletons;

    }
于 2013-02-12T14:07:51.777 に答える
3

これがあなたに役立つかどうかはわかりません。

独自の注釈を作成する必要があります。MyAnnot。そして、取得したいクラスにそのアノテーションを配置します。そして、次のコードを使用すると、インスタンス化されたBeanを取得できます。

ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
scanner.addIncludeFilter(new AnnotationTypeFilter(MyAnnot.class));
for (BeanDefinition beanDefinition : scanner.findCandidateComponents("com.xxx.yyy")){
    System.out.println(beanDefinition.getBeanClassName());
}

このようにして、カスタムアノテーションを持つすべてのBeanを取得できます。

于 2013-02-12T12:24:13.793 に答える
3

少し改善する必要がありました

@Resource
AbstractApplicationContext context;

@After
public void cleanup() {
    resetAllMocks();
}

private void resetAllMocks() {
    ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
    for (String name : context.getBeanDefinitionNames()) {
        Object bean = beanFactory.getSingleton(name);
        if (Mockito.mockingDetails(bean).isMock()) {
            Mockito.reset(bean);
        }
    }
}
于 2015-10-22T16:02:37.117 に答える
0

要旨 ApplicationContextAwareTestBaseを作成しました。

このヘルパー クラスは、次の 2 つのことを行います。

  1. すべての内部フィールドを null に設定します。これにより、Java は使用されなくなったメモリを解放できます。ただし、Spring ではあまり役に立ちません (Spring コンテキストはすべての Bean への参照を引き続き保持します)。

  2. @Afterコンテキスト内のすべての Bean でアノテーションが付けられたすべてのメソッドを見つけようとし、テスト後にそれらを呼び出します。

そうすれば、コンテキストを破棄/更新することなく、シングルトン/モックの状態を簡単にリセットできます。

例: モック DAO があります。

public void MockDao implements IDao {

    private Map<Long, Foo> database = Maps.newHashMap();

    @Override
    public Foo byId( Long id ) { return database.get( id ) );

    @Override
    public void save( Foo foo ) { database.put( foo.getId(), foo ); }

    @After
    public void reset() { database.clear(); }
}

注釈はreset()、内部状態をクリーンアップするために各単体テストの後に呼び出されることを確認します。

于 2013-02-12T15:16:08.590 に答える
0

以前の回答を使用して、Java 8 Streams API を使用するようにこれを更新しました。

@Inject
private ApplicationContext applicationContext;

@Before
public void resetMocks() {
    ConfigurableListableBeanFactory beanFactory = ((AbstractApplicationContext) applicationContext).getBeanFactory();
    Stream.of(applicationContext.getBeanDefinitionNames())
            .map(n -> beanFactory.getSingleton(n))
            // My ConfigurableListableBeanFactory isn't compiled for 1.8 so can't use method reference. If yours is, you can say
            // .map(ConfigurableListableBeanFactory::getSingleton)
            .filter(b -> Mockito.mockingDetails(b).isMock())
            .forEach(Mockito::reset);
}
于 2016-09-25T19:42:02.753 に答える