Как я могу симулировать завершение транзакции, используя JUnit с Spring и Hibernate, чтобы изолировать LazyInitializationException? - PullRequest
2 голосов
/ 01 июля 2010

Я пытаюсь написать тест, который изолирует ошибку загрузки свойства, так как сеанс не существует.

Следующий путь завершается неудачно

ERROR [http-8081-14] LazyInitializationException.setSessionAttribute(223) | could not initialize proxy - no Session
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:86)
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:140)
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190)
    at jaci.model.web.Shipment_$$_javassist_4.toString(Shipment_$$_javassist_4.java)
    at java.lang.String.valueOf(String.java:2827)
    at java.lang.StringBuilder.append(StringBuilder.java:115)
    at jaci.model.web.Web.toString(Web.java:259)
    at java.lang.String.valueOf(String.java:2827)
    at java.lang.StringBuffer.append(StringBuffer.java:219)
    at org.slf4j.helpers.MessageFormatter.arrayFormat(MessageFormatter.java:173)
    at org.slf4j.helpers.MessageFormatter.format(MessageFormatter.java:111)
    at org.slf4j.impl.Log4jLoggerAdapter.debug(Log4jLoggerAdapter.java:206)
    at jaci.web.ProcessingJobController.setSessionAttribute(ProcessingJobController.java:223)
    at jaci.web.ProcessingJobController.setSessionWeb(ProcessingJobController.java:219)
    at jaci.web.ProcessingJobController.initSessionJobAndWeb(ProcessingJobController.java:183)
    at jaci.web.ProcessingJobController.handlePost(ProcessingJobController.java:91)
    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.bind.annotation.support.HandlerMethodInvoker.doInvokeMethod(HandlerMethodInvoker.java:421)
    at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:136)
    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:326)
    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:313)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:875)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:807)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:511)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at com.opensymphony.sitemesh.webapp.SiteMeshFilter.obtainContent(SiteMeshFilter.java:129)
    at com.opensymphony.sitemesh.webapp.SiteMeshFilter.doFilter(SiteMeshFilter.java:77)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:378)
    at org.springframework.security.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)
    at org.springframework.security.intercept.web.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
    at org.springframework.security.ui.SessionFixationProtectionFilter.doFilterHttp(SessionFixationProtectionFilter.java:67)
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
    at org.springframework.security.ui.ExceptionTranslationFilter.doFilterHttp(ExceptionTranslationFilter.java:101)
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
    at org.springframework.security.providers.anonymous.AnonymousProcessingFilter.doFilterHttp(AnonymousProcessingFilter.java:105)
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
    at org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter.doFilterHttp(SecurityContextHolderAwareRequestFilter.java:91)
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
    at org.springframework.security.ui.preauth.AbstractPreAuthenticatedProcessingFilter.doFilterHttp(AbstractPreAuthenticatedProcessingFilter.java:69)
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
    at org.springframework.security.context.HttpSessionContextIntegrationFilter.doFilterHttp(HttpSessionContextIntegrationFilter.java:235)
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
    at org.springframework.security.util.FilterChainProxy.doFilter(FilterChainProxy.java:175)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:236)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:525)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
    at java.lang.Thread.run(Thread.java:619)

Подсветка

at jaci.web.ProcessingJobController.setSessionAttribute(ProcessingJobController.java:223)
at jaci.web.ProcessingJobController.setSessionWeb(ProcessingJobController.java:219)
at jaci.web.ProcessingJobController.initSessionJobAndWeb(ProcessingJobController.java:183)
at jaci.web.ProcessingJobController.handlePost(ProcessingJobController.java:91)

Для этого контроллера

@Controller
@RequestMapping("/processingJob.*")
public class ProcessingJobController {

    private static final String WEB_SESSION_ATTRIBUTE = "web";

    private static final Logger LOGGER = LoggerFactory.getLogger(ProcessingJobController.class);

    @Autowired
    private PrinterService printerService;

    @Autowired
    private WebService webService;

    @Autowired
    private UserService userService;

    @RequestMapping(method = RequestMethod.GET)
    public ModelAndView deleteMostRecentRange(final HttpServletRequest request) {
        LOGGER.debug(
                "Received a request to delete {} from {}.",
                this.lastCheckRangeOnJob(this.sessionJob(request)),
                this.sessionJob(request));
        Map<String, Object> processingJobModel = new HashMap<String, Object>();
        this.printerService.deleteMostRecentRange(this.sessionJob(request));
        return this.processingJobModelAndView(request, processingJobModel);
    }

    //FIXME Awful, awful, awful, awful, awful, awful, awful, awful, awful TAV
    @RequestMapping(method = RequestMethod.POST)
    public ModelAndView handlePost(
            @RequestParam(
                    value = JOB_SESSION_ATTRIBUTE,
                    required = false)
                final Long jobId,
            @RequestParam(
                    value = WEB_SESSION_ATTRIBUTE,
                    required = false)
                final Long webId,
            @RequestParam(
                    value = "new-end-icn",
                    required = false)
                final String newEndIcn,
            @RequestParam(
                    value = "rangeType",
                    required = false)
                final String newRangeType,
            final HttpServletRequest request) {

        Map<String, Object> processingJobModel = new HashMap<String, Object>();

        if (this.isInitialRequest(request)) {
            this.initSessionJobAndWeb(jobId, webId, request);
        } else if (this.isGetAvailableWebsRequest(jobId, webId, newEndIcn)) {
            this.setAvailableWebsInModel(processingJobModel);
        } else if (this.isChangeWebRequest(jobId, webId, newEndIcn)) {
            this.setSessionWeb(request, this.webService.getWeb(webId));
        } else if (this.isAddRangeRequest(jobId, webId, newEndIcn, newRangeType)) {
            this.addCheckRangeToJob(newEndIcn, newRangeType, request, processingJobModel);
        }

        return this.processingJobModelAndView(request, processingJobModel);

    }

    private void initSessionJobAndWeb(final Long jobId, final Long webId, final HttpServletRequest request) {
        this.setSessionJob(request, this.printerService.getJobForProcessing(jobId));
        this.setSessionWeb(request, this.webService.getWeb(webId));
    }

    private void setSessionWeb(final HttpServletRequest request, final Web web) {
        this.setSessionAttribute(request, WEB_SESSION_ATTRIBUTE, web);
    }

    private void setSessionAttribute(final HttpServletRequest request, final String sessionAttribute, final Object value) {
        LOGGER.debug("Received a request to set Session {} to {}", sessionAttribute, value);
        request.getSession().setAttribute(sessionAttribute, value);
    }

Учитывая это, как я могу написать тест, чтобы изолировать этот сбой и гарантировать, что я не сломаю его в будущем.Вот что у меня есть.

package jaci.web;

import static org.junit.Assert.assertNotNull;
import jaci.service.WebService;

import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;

@ContextConfiguration(locations = { "/applicationContext-data.xml", "/applicationContext-service.xml" })
public class ProcessingJobControllerTest
extends AbstractTransactionalJUnit4SpringContextTests {

    @Autowired
    private WebService webService;

    @Test
    public void logWebToString() {
        String web = this.webService.getWeb(-19L).toString();
        assertNotNull(web);
    }

}

Ответы [ 2 ]

2 голосов
/ 01 июля 2010

AbstractTransactionalJUnit4SpringContextTests - не более чем удобство для тестов, которые хотят что-то делать внутри транзакции. Нет причин, по которым вы не можете использовать более ручной подход.

Ваш тест мог бы сам вводиться с помощью PlatformTransactionManager, который затем может быть вызван программно (например, с использованием TransactionTemplate). Семантика будет такой же, как и , описанная в документации для программных транзакций в реальном коде.

Таким образом, ваш тест может начать транзакцию, выполнить некоторую работу, зафиксировать / откатить, а затем продолжить выполнять дополнительную работу, чтобы использовать путь lazy-init.

0 голосов
/ 01 июля 2010

В прошлом я успешно делал это, получая доступ к сеансу Hiberate и выполняя руководство .flush(); и .evict();

Я на самом деле использовал его так много, что поместил в метод Testing Superclass под названием clearSession()

Но из вашего кода я не вижу простого способа получить доступ к сеансу

...