web-dev-qa-db-ja.com

Spring JUnit:自動配線コンポーネントを自動配線コンポーネントでモックする方法

テストしたいSpringコンポーネントがあり、このコンポーネントには自動テストされた属性があり、ユニットテストの目的で変更する必要があります。問題は、クラスがpost-constructメソッド内でautowiredコンポーネントを使用するため、実際に使用される前に(ReflectionTestUtilsを介して)置き換えることができないことです。

どうすればいいですか?

これは私がテストしたいクラスです:

@Component
public final class TestedClass{

    @Autowired
    private Resource resource;

    @PostConstruct
    private void init(){
        //I need this to return different result
        resource.getSomething();
    }
}

そして、これがテストケースのベースです:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations= "classpath:applicationContext.xml")
public class TestedClassTest{

    @Autowired
    private TestedClass instance;

    @Before
    private void setUp(){
        //this doesn't work because it's executed after the bean is instantiated
        ReflectionTestUtils.setField(instance, "resource", new Resource("something"));
    }
}

Postconstructメソッドが呼び出される前にリソースを別のものに置き換える方法はありますか? Spring JUnitランナーに異なるインスタンスを自動配線するように指示したいですか?

53
NeplatnyUdaj

定義する@Autowired Beanがテストに必要なタイプである新しいtestContext.xmlを提供できます。

9
phury

Mockito を使用できます。 PostConstructとは具体的にはわかりませんが、これは一般に機能します:

// Create a mock of Resource to change its behaviour for testing
@Mock
private Resource resource;

// Testing instance, mocked `resource` should be injected here 
@InjectMocks
@Resource
private TestedClass testedClass;

@Before
public void setUp() throws Exception {
    // Initialize mocks created above
    MockitoAnnotations.initMocks(this);
    // Change behaviour of `resource`
    when(resource.getSomething()).thenReturn("Foo");   
}
51
Anna Zubenko

Spring Boot 1.4では、 @MockBean と呼ばれるテストアノテーションが導入されました。そのため、Spring Beanのモックとスパイは、Spring Bootによってネイティブにサポートされています。

18
luboskrnac

トピックに関するブログ投稿 を作成しました。また、Githubリポジトリへのリンクと実際の例も含まれています。

トリックは、元のSpring Beanを偽のSpring Beanでオーバーライドするテスト構成を使用することです。このトリックには、@Primaryおよび@Profile注釈を使用できます。

7
luboskrnac

Spring-reinjectでモックでBean定義をオーバーライドできます https://github.com/sgri/spring-reinject/

6

統合テストの別のアプローチは、新しい構成クラスを定義し、@ContextConfigurationとして提供することです。この構成では、Beanをモックできます。また、テスト/フローで使用しているすべてのタイプのBeanを定義する必要があります。例を提供するには:

@RunWith(SpringRunner.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
public class MockTest{
 @Configuration
 static class ContextConfiguration{
 // ... you beans here used in test flow
 @Bean
    public MockMvc mockMvc() {
        return MockMvcBuilders.standaloneSetup(/*you can declare your controller beans defines on top*/)
                .addFilters(/*optionally filters*/).build();
    }
 //Defined a mocked bean
 @Bean
    public MyService myMockedService() {
        return Mockito.mock(MyService.class);
    }
 }

 @Autowired
 private MockMvc mockMvc;

 @Autowired
 MyService myMockedService;

 @Before
 public void setup(){
  //mock your methods from MyService bean 
  when(myMockedService.myMethod(/*params*/)).thenReturn(/*my answer*/);
 }

 @Test
 public void test(){
  //test your controller which trigger the method from MyService
  MvcResult result = mockMvc.perform(get(CONTROLLER_URL)).andReturn();
  // do your asserts to verify
 }
}
3
Rzv Razvan