在Spring Web上下文中由Mock对象覆盖自动装配的字段

时间:2014-05-14 13:09:05

标签: java spring mocking

我们有带有控制器和服务层的Spring Web层,其服务具有自动装配的bean /服务。我们正试图通过Web层模拟它们来编写服务的集成测试用例。在测试用例中,我们创建了WebAppContext并将其部署在jetty服务器上。在我的测试用例中,我试图从服务器获取上下文并使用反射替换服务以模拟模拟对象。但问题是因为所有都是LAZILY自动装配,当实际的自动装配对象被初始化时,我的模拟被覆盖。

我们需要解决方案在运行测试用例的同时用上下文中的mock对象替换实际的初始化对象。

当我使用getBean(“beanName”)从上下文中获取bean时,bean中的所有自动连接字段都为null,任何原因和我从应用程序上下文中删除了'default-lazy-init'以避免延迟负荷。

见下面的代码,我有depositService&在AccountService中撤销服务。 当我从getBean()获得'Accountservice'时,它将这两个自动装配的varibles返回为null,即 depositService = null& withdrawService = null。

@service
public class AccountServiceImpl implements AccountService{

@autowired
private Depositservice depositService;

@autowired
private WithdrawService withdrawService;
}

3 个答案:

答案 0 :(得分:0)

您正在寻找的是由Springockito项目实施的。

您可以使用XML或注释轻松地将bean声明为模拟或spys。

我建议你尽可能让你的测试定期进行单元测试,因为你还是要使用模拟器。

答案 1 :(得分:0)

我通常在测试类路径中使用一些名为相同内容的特定文件来测试Spring上下文覆盖,这些文件在测试期间接管主类路径中的普通bean。然后显然我使用Spring Junit Runner和其他上下文注释来为我的上下文引入我想要的启动文件。

答案 2 :(得分:0)

最后我找到了答案。问题是当spring初始化autowired属性时,它会在它周围创建一个代理对象。因此,每当我们必须将模拟对象设置为任何属性时,我们应该在代理对象中设置它。

  1. 获取网络背景。
  2. 从需要注入mock的上下文中获取bean
  3. 创建模拟对象(我在这里使用Mockito来生成它)
  4. 使用reflection utils设置属性。
  5. 设置属性时,解包propxy对象,然后设置其属性。
  6. 以下是代码段:

    WebApplicationContext webContext = getWebContextBean();
    StaticApplicationContext context = new StaticApplicationContext(webContext);
    MockService mockObject = mock(DepositService.class );
    AccountServiceImpl service = context.getBean( AccountServiceImpl.class );
    ReflectionTestUtils.setField( unwrapProxy(service), "depositService", mockObject );
    context.refresh();
    

    UnwrapProxy将具有以下逻辑:

    if ( AopUtils.isAopProxy( bean ) && bean instanceof Advised ) {
            Advised advised = (Advised)bean;
            bean = advised.getTargetSource().getTarget();
        }
    return bean;
    

    从已部署应用的服务器获取上下文

    WebApplicationContext getWebContextBean() {
        WebAppContext jettyWebAppContext = (WebAppContext)server.getHandler();
        ServletContext servletContext = jettyWebAppContext.getServletHandler().getServletContext();
        WebApplicationContext springWebAppContext = WebApplicationContextUtils.getWebApplicationContext( servletContext );
        return springWebAppContext;
    }