2

I have a spring service method that gets an object stored in the session (using FacesContext) as follows:

(MyObject)((HttpServletRequest) FacesContext
                .getCurrentInstance().getExternalContext().getRequest())
                .getSession().getAttribute("myObject");

and I would like to put that object in session in unit test before invoking the method.

so i tried the solution in this post:

Spring Test session scope bean using Junit

and in my test method i put the object in session before calling the service, but the service throws an exception when trying to get the object from the session, i guess that this is because the facescontext is not available, what do you think ?

I am using Spring, Junit, JSF2, please advise, thanks.

Community
  • 1
  • 1
Java Dev
  • 21
  • 1
  • 1
  • 3

3 Answers3

2

With Spring 3.2 this is very easier

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(...)
@WebAppConfiguration
public class SessionTest {

    @Autowired
    MockHttpSession session;


    @Test
    public void sessionAttributeTest() throws Exception {

        MyObject myObject = session.getAttribute("myObject");
        ...

    }
}

More information: Request and Session Scoped Beans

MariuszS
  • 30,646
  • 12
  • 114
  • 155
1

I'm assuming that you're talking about HttpSession.

Create a mock session, tell the mock session to always return this object when its getAttribute method is called with the name used by the object under test, and pass this mock session rather than a real one to the object under test.

Mocking APIs such as Mockito or EasyMock will help doing that.

EDIT: Suppose the method you want to test looks like this:

public String foo() {
    // some lines of code
    MyObject o = 
        (MyObject)((HttpServletRequest) FacesContext
             .getCurrentInstance().getExternalContext().getRequest())
             .getSession().getAttribute("myObject");
    // some more lines of code, using o.
}

You could refactor it like this:

public String foo() {
    // some lines of code
    MyObject o = getMyObjectFromSession();
    // some more lines of code, using o.
}

protected MyObject getMyObjectFromSession() {
    return (MyObject)((HttpServletRequest) FacesContext
             .getCurrentInstance().getExternalContext().getRequest())
             .getSession().getAttribute("myObject");
}

And you could then use a mocking framework to do something like this (pseudo-code):

// mockFoobar is the object to test. We just mock its getMyObjectFromSession method
FooBar mockFoobar = mock(Foobar.class);
MyObject objectInSession = new MyObject();
when(mockFoobar.getMyObjectFromSession()).thenReturn(objectInSession);

String s = mockFoobar.foo();
assertEquals("expected result", s);
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • I guess that the code you really want to test is the code before and after this call to FacesContext. If so, externalize the call to FacesContext into a protected helper method or object, mock that helper method/object to make it return whatever you want, and test the code. – JB Nizet Dec 15 '11 at 12:05
  • no, i want to get the object from session in the service as noted above, when invoking the service from unit test, it works fine when running the application, but gives null pointer when invoking unit test. – Java Dev Dec 15 '11 at 12:16
0

Add spring-mock to your test classpath which gives you org.springframework.mock.web.MockHttpSession. This is a pretty simple implementation that you can create with new without a Java EE container.

The JAR also contains mocks for requests, responses and everything else.

Another solution is to use MockRunner which does the same.

Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
  • I'd like to see a full example of this use. I can create a `MockHttpSession`. Any calls to `MockHttpSession.invalidate()` throw an exception, though, saying the session has already been invalidated. – Christopher Schneider Feb 24 '17 at 15:08
  • ...And spoke too soon. I was invalidating the session, and then trying a `session.getAttribute()`, expecting it to return null. Instead, it throws the `IllegalStateException` because the session is already invalidated. – Christopher Schneider Feb 24 '17 at 15:20