web-dev-qa-db-ja.com

ポストコンストラクトを使用したSpringBeanのテスト

私はこれに似た豆を持っています:

@Service
public class A {

    @Autowired
    private B b;

    @PostConstruct
    public void setup() {
       b.call(param);
    }
}

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = { Application.class, Config.class })
@WebIntegrationTest(randomPort = true)
public class Test {

    @Autowired
    B b;

    @Before
    public void setUp() throws Exception {
        when(b.call(any())).thenReturn("smth");
    }

    @Test
    public void test() throws Exception {
        // test...
    }
}

問題は、テストの実行時にPostConstructsetUpの前に呼び出されることです。

9
Andy

nitAのテストを記述したい場合は、Springを使用しないでください。代わりに、Aを自分でインスタンス化し、Bのスタブ/モックを渡します(コンストラクターインジェクションまたはReflectionTestUtilsを使用してプライベートフィールドを設定します)。

例えば:

@Service
public class A {

    private final B b;    

    @Autowired
    public A(B b) {
        this.b = b;
    }

    @PostConstruct
    public void setup() {
       b.call(param);
    }
}

-

public class Test {

    @Test
    public void test() throws Exception {
        B b = mock(b);
        A a = new A(b);
        // write some tests for A
    }

}

integrationテストを記述したいため、Springを使用する必要がある場合は、別のアプリケーションコンテキストを使用して、Bをスタブ/モックに置き換えます。

たとえば、Bが次のようにProductionクラスでインスタンス化されると仮定します。

@Configuration
public class Production {

    @Bean
    public B b() {
        return new B();
    }

}

テスト用に別の@Configurationクラスを作成します。

@Configuration
public class Tests {

    @Bean
    public B b() {
        // using Mockito is just an example
        B b = Mockito.mock(B.class); 
        Mockito.when(b).thenReturn("smth"); 
        return b;
    }

}

テストでは、@SpringApplicationConfigurationアノテーションを使用して参照してください。

@SpringApplicationConfiguration(classes = { Application.class, Tests.class })
14
hzpz

もう1つの方法は、テストでアプリケーションコンテキストを自分でインスタンス化し、コンテキストを更新する前にモックを挿入することです。たとえば、次のようになります。

@Configuration
@ComponentScan
public class TestConfiguration {}
...
ClassToMock mock = mock(ClassToMock.class);
AnnotationConfigApplicationContext c = new AnnotationConfigApplicationContext();
c.getDefaultListableBeanFactory().registerResolvableDependency(
        ClassToMock.class,
        mock);
c.register(TestConfiguration.class);
c.refresh();

この代替手段は、コンテキストに@PostConstructアノテーションがあり、事前にモックに期待値を設定する場合に役立ちます。

0
beluchin