7

I'm trying to test the correct information given from DB using the services and the correct logic of the methods. In this simple example, I'm only using the statement assertEquals to compare the id given for the roleService, but I'm still getting errors. I have the following code:

[UPDATED]

Test method:

@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 is the service class that consult Database information using objectifyService from Google App Engine.

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>

Into the com.project.surveyengine.config I have the folliwing three classes:

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
    }
}

I'm getting this errors:

Dec 20, 2016 4:40:03 PM com.google.appengine.api.datastore.dev.LocalDatastoreService init INFO: Local Datastore initialized: Type: High Replication Storage: In-memory

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

RoleServiceTest.java:111 = assertEquals("Correct test", Long.valueOf("5067160539889664"), role.getId());
Angel Cuenca
  • 1,637
  • 6
  • 24
  • 46
  • 1
    My personal opinion is that first of all you need to decide what kind of test you want. Is it really a sort of an _integration test_? Does it make sense to connect to the real DB and have all the associated boilerplate configured so you can verify some complex logic in your module? Or is it just a _unit test_ to verify that your service behaves as expected? Case in which you can simply mock the service's dependencies (mockito, easy mock, etc) and just instantiate it and verify the output of its methods. I can't tell from your description but to me it seems the latter, hence my suggestion. – Morfic Dec 07 '16 at 17:00
  • Yes, previously I was using Mockito, but I have some methods that I need to mock several repositories, so this becomes a complex job. The idea is checks the expected result from a complex module, but also combined using real information from DB. That's why I'm using the services into the test. – Angel Cuenca Dec 07 '16 at 17:10
  • The exception is really straightforward - your test can't find `defaultServletHandlerMapping` bean. That happens because of `WebConfig` class, so, you should add it to the filtering: `Filter(type = FilterType.ANNOTATION, value = Configuration.class), Filter(type = FilterType.ANNOTATION, value = WebConfig.class) })` – Enigo Dec 08 '16 at 07:52
  • But overall I totally agree with @Morfic . You should never use real database data for test purposes. If you want to have an integration tests embedded database (H2, Derby) is a nice option. You should keep junit test small and clear. The test should ideally test the class only but not the whole application logic. – Enigo Dec 08 '16 at 07:55
  • @Enigo Even so, when I add it to the filtering, it gives to me the same error. – Angel Cuenca Dec 15 '16 at 14:36
  • Consider posting the full stack trace to provide the complete context of the error, so we know that it's not in fact another class annotated with @EnableWebMvc, or some other dependency on WebApplicationContext. – Adam Dec 17 '16 at 20:59
  • @Adam What else do you need to see ? I post all the code involved in testing. – Angel Cuenca Dec 18 '16 at 16:06
  • A stack trace removes the unknown of which classes are involved, since it gives you the exact source files and line numbers. Otherwise, the community can only make guesses or make the assumption that it's one of the classes posted in the question. It's more relevant since you mention you get the same error when adding WebConfig to the filter. – Adam Dec 20 '16 at 00:06
  • I can post whatever code you need. I think it provides all the necessary code. But I found that when I add @WebAppConfiguration it onlt gives to me: javax/servlet/SessionCookieConfig. Otherwise the errors are the ones I published. – Angel Cuenca Dec 20 '16 at 15:09

1 Answers1

3

Did you try to add @WebAppConfiguration as suggested in the documentation http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/test/context/web/WebAppConfiguration.html ?

I'd wirte your test code in this way

@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());
    }

}

as you can see i added the annotation @WebAppConfiguration too

I hope this can help you

Angelo Immediata
  • 6,635
  • 4
  • 33
  • 65
  • I get this error: java.lang.NoClassDefFoundError: javax/servlet/SessionCookieConfig – Angel Cuenca Dec 19 '16 at 03:51
  • This is related to the fact that you don't have some lib under your classpath; are yuo using maven? you can add servlet API dependency to the pom.xml – Angelo Immediata Dec 19 '16 at 08:25
  • Yes I'm using maven. And also I added the servlet-api dependency, so the error is the same. – Angel Cuenca Dec 19 '16 at 15:57
  • Can you post the details of the servlet-api dependency you've added, so it can be verified as correct? – Adam Dec 20 '16 at 00:09
  • Sure @Adam. javax.servlet servlet-api 2.5 provided – Angel Cuenca Dec 20 '16 at 15:03
  • @Adam I change the two servlet-api dependency posted in the question: http://stackoverflow.com/questions/21561432/failed-to-load-applicationcontext-during-spring-unit-test. Now my error is different, I updated the question. Also I have a doubt, this connection is with the local datastore or with real datastore in GAE. I need the connection with the real DB. – Angel Cuenca Dec 20 '16 at 16:50
  • As this answer solved your original question, consider accepting it and posting a new question that refers back to this one for context instead of creating a [chameleon question](http://meta.stackoverflow.com/questions/275138/how-to-deal-with-op-asking-another-questions-after-answering-original-question/275140). – Adam Dec 24 '16 at 00:15