0

There is a rest web service working perfectly when I evoke from other application but it fails when I evoke from Junit tester. I read a lot in the last hours and, if I understood correctly, the error in the subject is happening for two possible reasons: 1 - when I use MockMvc it is ignoring the JNDI and 2 - there aren't the jars required in classpath. About the jars, I don't think it can be the cause because it does run correctly when called from other application. About the jndi, I am quite confuse why the container can provide the datasource when webs service is called from other application but fails when called from a mock tester. The closest question I found about it is How to test a mocked JNDI datasource with Spring?. In this thread it seems that the last comment gave a good solution but I wasn't able to implement mainly because there isn't jndi file definition with "jee:jndi-lookup". In few words, the rest web service is a controller exposing a method and inside this method there is a place where is getting a connection. Everything that goes beyond the controler I am not allowed to change. How can I use MockMvc to test this rest web service? Why the lock up doesn't work when the rest service is evoked from a mock tester? Is there a way to add some configuration in test-mvc-dispatcher-servlet.xml to make "ic.lookup("java:comp/env/jdbc/MHE")" runs?

//the connection is provided from this method and I can't change it

public Connection getConnection()throws Exception{
              try{
                     InitialContext ic = new InitialContext();
                     DataSource ds = (DataSource) ic.lookup("java:comp/env/jdbc/MHE"); //the error happens here

//rest web service

@Controller
@RequestMapping("/log")
public class Lo_Controller {
       @Autowired
       private Mhe_Handler mhe_Handler; //now Autowired 

       @Autowired
       private Lo_Mas60010 lo_Mas60010;

       @Autowired
       private LogDisplay testReturn;

       @ExceptionHandler(Exception.class)
       @ResponseStatus(value=HttpStatus.NOT_FOUND,reason="Contact not found")
       public void notFound() {


              System.out.println("error ...");
       }

       @RequestMapping(value="display/last", method=RequestMethod.POST)
       @ResponseBody
       @ResponseStatus(HttpStatus.OK)
       public LogDisplay getFirst(@RequestBody Mas60010 mas60010) {

              Connection con; // it is the only object not Autowired inside the Controler but take a note that the error happens inside mhe_Handler.getConnection()
              try {
                     con = mhe_Handler.getConnection(); 

//MockMvc

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration("classpath:/com/myCompany/mhe/test/test-mvc-dispatcher-servlet.xml")
public class RestErrorHandlingTest {


    @Autowired
    private WebApplicationContext wac;

    @Autowired
    private LogDisplay logDisplay;

       @Autowired
       private Mas60010 _mas60010;

    private MockMvc mockMvc;

    @Before
    public void setup() {
        this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();

     }

    @Test
    public void postLog() throws Exception {

       Mas60010 _mas60010 = new Mas60010(
                      ... the parameters here, not relevant information
                           );

       ObjectMapper mapper = new ObjectMapper();

       this.mockMvc.perform(
                     post("/log/display/last")
                     .contentType(
                                  new MediaType(
                                                MediaType.APPLICATION_JSON.getType(),
                                                MediaType.APPLICATION_JSON.getSubtype(),
                                                Charset.forName("utf8")
                                                )
                                  )
                     .content(mapper.writeValueAsBytes(_mas60010))
                     )
                     .andExpect(status().isBadRequest())
                           .andExpect(status().isOk())
                           .andExpect(content().contentType("application/json"))
                           .andExpect(model().attribute("logDisplay", logDisplay));

//test-mvc-dispatcher-servlet.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       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
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">

       <context:annotation-config />
       <mvc:annotation-driven />
       <context:component-scan base-package="com.myCompany.mhe.common.controller, com.myCompany.mhe.log.handler, com.myCompany.mhe.utilities, com.myCompany.mhe.log.domain" />
       <context:property-placeholder location="classpath:restServices.properties"/>


       <mvc:resources mapping="/**" location="/" />

       <bean
              class="org.springframework.web.servlet.view.InternalResourceViewResolver">
              <property name="prefix">
                     <value>/WEB-INF/pages/</value>
              </property>
              <property name="suffix">
                     <value>.jsp</value>
              </property>
       </bean>


    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <property name="messageConverters">
            <list>
                <ref bean="jsonMessageConverter"/>
            </list>
        </property>
    </bean>


    <bean id="jsonMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
    </bean>


</beans>

//error log

Dec 23, 2014 8:19:29 AM org.springframework.test.context.support.AbstractTestContextBootstrapper getDefaultTestExecutionListenerClassNames
INFO: Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener]
Dec 23, 2014 8:19:29 AM org.springframework.test.context.support.AbstractTestContextBootstrapper instantiateListeners
INFO: Could not instantiate TestExecutionListener [org.springframework.test.context.transaction.TransactionalTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their required dependencies) available. Offending class: [org/springframework/transaction/interceptor/TransactionAttributeSource]
Dec 23, 2014 8:19:29 AM org.springframework.test.context.support.AbstractTestContextBootstrapper instantiateListeners
INFO: Could not instantiate TestExecutionListener [org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their required dependencies) available. Offending class: [org/springframework/transaction/interceptor/TransactionAttribute]
Dec 23, 2014 8:19:29 AM org.springframework.test.context.support.AbstractTestContextBootstrapper getTestExecutionListeners
INFO: Using TestExecutionListeners: [org.springframework.test.context.web.ServletTestExecutionListener@4a738d08, org.springframework.test.context.support.DependencyInjectionTestExecutionListener@68302e67, org.springframework.test.context.support.DirtiesContextTestExecutionListener@3336a1a1]
Dec 23, 2014 8:19:30 AM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [com/myCompany/mhe/test/test-mvc-dispatcher-servlet.xml]
Dec 23, 2014 8:19:31 AM org.springframework.beans.factory.support.DefaultListableBeanFactory registerBeanDefinition
INFO: Overriding bean definition for bean 'logDisplay': replacing [Generic bean: class [com.myCompany.mhe.log.domain.LogDisplay]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [C:\STS\wsRestTemplate\MHE_original\WebContent\WEB-INF\classes\com\myCompany\mhe\log\domain\LogDisplay.class]] with [Generic bean: class [com.myCompany.mhe.log.domain.LogDisplay]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [com/myCompany/mhe/test/test-mvc-dispatcher-servlet.xml]]
Dec 23, 2014 8:19:31 AM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.web.context.support.GenericWebApplicationContext@68a53de4: startup date [Tue Dec 23 08:19:31 CST 2014]; root of context hierarchy
Dec 23, 2014 8:19:32 AM org.springframework.core.io.support.PropertiesLoaderSupport loadProperties
INFO: Loading properties file from class path resource [restServices.properties]
Dec 23, 2014 8:19:32 AM org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor <init>
INFO: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
Dec 23, 2014 8:19:32 AM org.springframework.web.servlet.handler.AbstractHandlerMethodMapping registerHandlerMethod
INFO: Mapped "{[/log/display/last],methods=[POST],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public com.myCompany.mhe.log.domain.LogDisplay com.myCompany.mhe.common.controller.Lo_Controller.getFirst(com.myCompany.mhe.log.domain.Mas60010)
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Dec 23, 2014 8:19:33 AM org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter initControllerAdviceCache
INFO: Looking for @ControllerAdvice: org.springframework.web.context.support.GenericWebApplicationContext@68a53de4: startup date [Tue Dec 23 08:19:31 CST 2014]; root of context hierarchy
Dec 23, 2014 8:19:33 AM org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter initControllerAdviceCache
INFO: Looking for @ControllerAdvice: org.springframework.web.context.support.GenericWebApplicationContext@68a53de4: startup date [Tue Dec 23 08:19:31 CST 2014]; root of context hierarchy
Dec 23, 2014 8:19:33 AM org.springframework.web.servlet.handler.AbstractUrlHandlerMapping registerHandler
INFO: Mapped URL path [/**] onto handler 'org.springframework.web.servlet.resource.ResourceHttpRequestHandler#0'
Dec 23, 2014 8:19:33 AM org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter initControllerAdviceCache
INFO: Looking for @ControllerAdvice: org.springframework.web.context.support.GenericWebApplicationContext@68a53de4: startup date [Tue Dec 23 08:19:31 CST 2014]; root of context hierarchy
Dec 23, 2014 8:19:58 AM org.springframework.mock.web.MockServletContext log
INFO: Initializing Spring FrameworkServlet ''
Dec 23, 2014 8:19:58 AM org.springframework.web.servlet.FrameworkServlet initServletBean
INFO: FrameworkServlet '': initialization started
Dec 23, 2014 8:19:58 AM org.springframework.web.servlet.FrameworkServlet initServletBean
INFO: FrameworkServlet '': initialization completed in 183 ms
javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial
       at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:645)
       at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288)
       at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:325)
       at javax.naming.InitialContext.lookup(InitialContext.java:392)
       at com.myCompany.mhe.Mhe_Handler.getConnection(Mhe_Handler.java:40)
       at com.myCompany.mhe.common.controller.Lo_Controller.getFirst(Lo_Controller.java:59)
       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
       at java.lang.reflect.Method.invoke(Method.java:597)
       at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215)
       at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
       at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
       at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:781)
       at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:721)
       at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
       at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943)
       at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877)
       at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
       at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:868)
       at javax.servlet.http.HttpServlet.service(HttpServlet.java:595)
       at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
       at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:65)
       at javax.servlet.http.HttpServlet.service(HttpServlet.java:668)
       at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:167)
       at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134)
       at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:144)
       at com.myCompany.mhe.test.RestErrorHandlingTest.postLog(RestErrorHandlingTest.java:151)
       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
       at java.lang.reflect.Method.invoke(Method.java:597)
       at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
       at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
       at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
       at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
       at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
       at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:73)
       at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82)
       at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:73)
       at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
       at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:217)
       at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:83)
       at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
       at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
       at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
       at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
       at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
       at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
       at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:68)
       at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
       at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:163)
       at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
       at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
       at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
       at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
       at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
       at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Community
  • 1
  • 1
Jim C
  • 2,519
  • 13
  • 54
  • 105

1 Answers1

0

your controller is not designed to be testable. the dependency Mhe_Handler is instantiated as local variable in method getFirst, so there is no way to mock it out in unit test. one solution is to extract it as a private field and autowire it, which is one of the most important benefits of dependency injection:

class Controller {

    //inject real Mhe_Handler backed by jndi datasource in production
    //while inject mockups in unit test
    @Autowired private Mhe_Handler mhe_Handler;

    public LogDisplay getFirst() { 
        //inject dependency instead of hard-wire it
        mhe_Handler.getConnection()

    }

}
Septem
  • 3,484
  • 1
  • 18
  • 19