使用Spring 3.2和Mockito进行控制器单元测试时的上下文初始化问题



我试图为我的控制器提供一个干净的单元测试。这个控制器有一个服务作为依赖,而这个服务有一个数据源作为依赖。

测试如下:

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration
public class ContentActionWebServiceControllerTest {
  @Autowired
  private WebApplicationContext wac;
  private MockMvc mockMvc;
  @Autowired
  private MyService myService;
  @Test
  public void getRequestActionList() throws Exception {
    when(...)
    perform(...);
    verify(...);
  }
  @Configuration
  @ImportResource("...")
  static class MyTestConfiguration {
    @Bean
    public MyService myService() {
      return Mockito.mock(MyService.class);
    }
  }
}

MyService类似于

@Service
public class MyService {
  @Autowired
  private MyDataSource myDatasource;
  ...
}

因为MyService作为一个Autowired属性MyDataSource,上下文没有初始化,因为它没有找到任何MyDataSource类型来满足MyService的@Autowired注释。但它为什么要尝试解析这个注释呢?这是个玩笑吗?

Mockito确实使用cglib来创建MyService的新子类(并使用mock方法覆盖所有方法)。

但是,父类的依赖项仍然会被注入,因为这就是Spring的工作方式:

如果你有一个父类有一些@Autowired字段,并且子类继承了这个父类,那么Spring将在实例化子类时注入父类的@Autowired字段。我猜你的情况也是一样的。

如果您使用MyService的接口,那么您的问题将得到解决。

如果它应该是一个单元测试(而不是集成测试),您甚至不需要使用Spring,您可以使用JUnit+Mockito来完成所有工作。您可以简单地创建支持对象的模拟(通过@Mock)并将它们注入测试对象(通过@InjectMocks),而不是从Spring上下文中创建@Autowire依赖项。我相信你的代码可以简化为这样的东西(概念上):

@RunWith(MockitoJUnitRunner.class)
public class ContentActionWebServiceControllerTest {
  @Mock
  private Service mockServiceUsedByController;
  @InjectMocks
  private YourController testee;
  @Test
  public void getRequestActionList() throws Exception {
    assertFalse(testee.getRequestActionList().isEmpty());
    // etc.
  }
}

相关内容

  • 没有找到相关文章

最新更新