【问题标题】:How to get Database connection in Spring using JUnit?如何使用 JUnit 在 Spring 中获取数据库连接?
【发布时间】:2017-04-22 16:38:22
【问题描述】:

我正在尝试使用服务和方法的正确逻辑来测试从 DB 提供的正确信息。在这个简单的示例中,我只使用语句 assertEquals 来比较为 roleService 提供的 id,但我仍然遇到错误。我有以下代码:

[更新]

测试方法:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = { "classpath:applicationContext.xml" })
@Transactional
@WebAppConfiguration
@ComponentScan(basePackages ={ "com.project.surveyengine" },
            excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = Configuration.class) ,
                              @ComponentScan.Filter(type = FilterType.ANNOTATION, value = WebConfig.class)})
public class RoleServiceTest {

@Configuration
    static class ContextConfiguration {    
        @Bean
        public RoleService roleService() {
            RoleService roleService = new RoleService();
            // set properties, etc.
            return roleService;
        }
    }

    private final LocalServiceTestHelper helper =
            new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig()
                    .setDefaultHighRepJobPolicyUnappliedJobPercentage(100));

    private Closeable closeable;

    @Before
    public void setUp() {
        helper.setUp();
        ObjectifyService.register(Role.class);
        closeable = ObjectifyService.begin();
    }

    @After
    public void tearDown() {
        closeable.close();
        helper.tearDown();
    }

    @Autowired
    private RoleService roleService;

    @Test
    public void existsRole() throws Exception{
        Role role = roleService.getByName("ROLE_ADMIN");
        assertEquals("Correct test", Long.valueOf("5067160539889664"), role.getId());
    }

}

RoleService 是使用来自Google App EngineobjectifyService 查询数据库信息的服务类。

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config /> 

    <context:component-scan base-package="com.project.surveyengine.config"/>

    <!--Controllers-->
    <bean id="inboxController" class="com.project.surveyengine.controller.InboxController" autowire="byType"></bean>
    <bean id="mailController" class="com.project.surveyengine.controller.MailController" autowire="byType"></bean>
    <bean id="loginController" class="com.project.surveyengine.controller.LoginController" autowire="byType"></bean>
    <bean id="initController" class="com.project.surveyengine.controller.InitController" autowire="byType"></bean>

    <!--Services-->
    <bean id="answerService" class="com.project.surveyengine.service.impl.AnswerService" autowire="byType"></bean>
    <bean id="blobService" class="com.project.surveyengine.service.impl.BlobService" autowire="byType"></bean>
    <bean id="mailService" class="com.project.surveyengine.service.impl.MailService" autowire="byType"></bean>
    <bean id="caseService" class="com.project.surveyengine.service.impl.CaseService" autowire="byType"></bean>
    <bean id="roleService" class="com.project.surveyengine.service.impl.RoleService" autowire="byType"></bean>
</beans>

进入com.project.surveyengine.config我有以下三个类:

1)

public class MyXmlWebApplicationContext extends XmlWebApplicationContext {
    protected void initBeanDefinitionReader(XmlBeanDefinitionReader beanDefinitionReader) {
        super.initBeanDefinitionReader(beanDefinitionReader);
        if (SystemProperty.environment.value() == SystemProperty.Environment.Value.Production) {
            beanDefinitionReader.setValidating(false);
            beanDefinitionReader.setNamespaceAware(true);
        }
    }
}

2)

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter{    
  @Bean
  UrlBasedViewResolver resolver(){
    UrlBasedViewResolver resolver = new UrlBasedViewResolver();
    resolver.setPrefix("/views/");
    resolver.setSuffix(".jsp");
    resolver.setViewClass(JstlView.class);
    return resolver;
  }

  @Override
  public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/statics/**").addResourceLocations("/statics/");
  }    
}

3)

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityContext extends WebSecurityConfigurerAdapter {    
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/statics/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .formLogin()
                //...more code
    }
}

我收到此错误:

2016 年 12 月 20 日下午 4:40:03 com.google.appengine.api.datastore.dev.LocalDatastoreService 初始化 信息:本地数据存储已初始化:类型:高复制存储: 内存中

java.lang.NullPointerException 在 com.project.surveyengine.service.impl.RoleServiceTest.existsRole(RoleServiceTest.java:111)

RoleServiceTest.java:111 = assertEquals("Correct test", Long.valueOf("5067160539889664"), role.getId());

【问题讨论】:

  • 我个人的看法是,首先你需要决定你想要什么样的测试。它真的是一种集成测试吗?连接到真实的数据库并配置所有相关的样板文件是否有意义,以便您可以验证模块中的一些复杂逻辑?还是只是一个单元测试来验证您的服务是否符合预期?在这种情况下,您可以简单地模拟服务的依赖项(mockito、easy mock 等)并实例化它并验证其方法的输出。我无法从您的描述中看出,但对我来说似乎是后者,因此我的建议。
  • 是的,以前我使用的是 Mockito,但是我有一些方法需要模拟多个存储库,所以这变得很复杂。这个想法是检查来自复杂模块的预期结果,但也使用来自 DB 的真实信息进行组合。这就是我在测试中使用这些服务的原因。
  • 异常很简单——你的测试找不到defaultServletHandlerMapping bean。发生这种情况是因为 WebConfig 类,因此,您应该将其添加到过滤中:Filter(type = FilterType.ANNOTATION, value = Configuration.class), Filter(type = FilterType.ANNOTATION, value = WebConfig.class) })
  • 但总的来说我完全同意@Morfic。您永远不应该将真实的数据库数据用于测试目的。如果您想拥有一个集成测试嵌入式数据库(H2、Derby)是一个不错的选择。您应该保持 junit 测试小而清晰。理想情况下,测试应该只测试类而不是整个应用程序逻辑。
  • @Enigo 即便如此,当我将它添加到过滤器时,它也会给我同样的错误。

标签: java spring unit-testing google-app-engine junit


【解决方案1】:

您是否尝试按照文档http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/test/context/web/WebAppConfiguration.html 中的建议添加@WebAppConfiguration

我会这样写你的测试代码

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = { "classpath:applicationContext.xml" })
@TransactionConfiguration(transactionManager="txMgr", defaultRollback=false)
@Transactional
@WebAppConfiguration
@ComponentScan(basePackages ={ "com.project.surveyengine" }, excludeFilters = {
                @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Configuration.class) })
public class RoleServiceTest {

    @Autowired
    private RoleService roleService;

    @Test
    public void existsRole() throws Exception{
        Role role = roleService.getByName("ROLE_ADMIN");
        assertEquals("Correct test", Long.valueOf("5067160539889664"), role.getId());
    }

}

如您所见,我也添加了注释 @WebAppConfiguration

希望对你有帮助

【讨论】:

  • 我得到这个错误:java.lang.NoClassDefFoundError: javax/servlet/SessionCookieConfig
  • 这与您的类路径下没有一些库有关;你在使用maven吗?您可以将 servlet API 依赖项添加到 pom.xml
  • 是的,我正在使用 Maven。而且我还添加了servlet-api依赖,所以错误是一样的。
  • 您能否发布您添加的 servlet-api 依赖项的详细信息,以便验证它是否正确?
  • 当然@Adam。 javax.servletservlet-api2.5provided
猜你喜欢
  • 2021-09-24
  • 1970-01-01
  • 2012-03-19
  • 2013-08-07
  • 1970-01-01
  • 1970-01-01
  • 2015-04-27
  • 2015-12-30
  • 2019-06-15
相关资源
最近更新 更多