I am trying to set the session for testing, but i am getting NullPointerException. I have tried a couple of of ways, but could not succeed.
class Test {
public void testOne() {
HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(true);
session.setAttribute("test", someValue()); //session value is null
}
}
//This is my Unit Test which have one method giving exception.Why the session is giving null value....
Class TestUnitTest {
private TestUnit testUnit;
private ExternalContext externalContext;
private HttpServletRequest request;
private HttpSession httpSession;
#Before
public void init() {
testUnit = new TestUnit();
externalContext = Mockito.mock(ExternalContext.class);
Mockito.when(FacesContext.getCurrentInstance().getExternalContext()).thenReturn(externalContext);
request = Mockito.mock(HttpServletRequest.class);
Mockito.when(FacesContext.getCurrentInstance().getExternalContext().getRequest()).thenReturn(request);
httpSession = Mockito.mock(HttpSession.class);
Mockito.when((request.getSession())).thenReturn(httpSession);
//I am getting null pointer exception while implementing in this way
#Test
public void testvalueTest() {
testUnit.testOne(); //Null pointer exception
verify(httpSession).setAttribute("test", someValue());
}
//I am getting Wanted not Invoked while implementing in this way Wanted not Invoked
#Test
public void testvalueTest() {
verify(httpSession).setAttribute("test", someValue()); //Wanted not invoked
testUnit.testOne();
}
}
What I am doing wrong - what is the right approach to set the session?
externalContext = Mockito.mock(ExternalContext.class);
Mockito.when(FacesContext.getCurrentInstance().getExternalContext()).thenReturn(externalContext);
request = Mockito.mock(HttpServletRequest.class);
Mockito.when(FacesContext.getCurrentInstance().getExternalContext().getRequest()).thenReturn(request);
Mockito works by overriding instance methods, and can't override static methods. Though PowerMock does allow static method mocking, you can usually refactor the calls to static methods into instance methods and then mock using Mockito or other test override techniques.
Related
I have a #RestController in which every method needs to pass a (WebSSO) cookie down to a service. The service in turn uses the cookie for authentication. I am autowiring the service bean in controller. The service has a setter setCredentials(String webSSOCookie). One easy way is to call this setter in every method. I would like to do it better way; for instance using HandlerInterceptor. However the HandlerInterceptor does not have access to the controller (and hence its members) - am I right?
In jersey I could use filter. How do I achieve it in SPRING?
#RestController
#RequestMapping("/documents")
public class ECMRestController {
#Autowired
public ECMService ecmService;
#RequestMapping(value="/{documentId}", method=RequestMethod.DELETE)
public void deleteDocument(#RequestParam("documentId") String documentId) throws IllegalArgumentException, HttpClientErrorException {
// I could get and pass the cookie to ecmService in every method.
// ecmService.setCredentials(webSSOCookieObtainedfromRequest);
// However I don't want to do it that way.
ecmService.deleteDocument(documentId);
}
// Other REST Methods that need to pass the cookie in the same way.
}
You can request the SecurityContextHolder to query the current Authentication that you had customized in a filter.
MyCustomAuth auth = (MyCustomAuth) SecurityContextHolder.getContext().getAuthentication();
auth.getCookie();
or you can just use ThreadLocal in a context that can be retrieve from anywhere:
public class CookieContext {
private static final ThreadLocal<Cookie> COOKIE = new ThreadLocal<>();
private static final CookieContext INSTANCE = new CookieContext();
public void setCookie(Cookie value) {
COOKIE.set(value);
}
public Cookie getCookie() {
return COOKIE.get();
}
public static CookieContext getContext() {
return INSTANCE;
}
}
public class CookieInterceptor extends HandlerInterceptorAdapter {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
CookieContext context = CookieContext.getContext();
context.setCookie(request.getCookies()[0]);
}
}
I am facing issues in mocking the data for the methods which are being called without the reference e.g getMethod(); don't know how will mocking framework know about it. Below is the code for which am facing issue am not able to set HttpRequest and URIInfo in my code.
Is it possible to bypass the method.
Class A {
private HttpServletRequest httpRequest;
private UriInfo uriInfo;
public HttpServletRequest getReq() {
return httpRequest;
}
public void setReq(HttpServletRequest req) {
this.httpRequest = req;
}
public UriInfo getUriInfo() {
return uriInfo;
}
public void setUriInfo(UriInfo uriInfo) {
this.uriInfo = uriInfo;
}}
class B extends A {
// some code
}
class C extends B {
protected Object executeCall(Object beIn) throws Exception{
prepareUpdateConfigurationRequest();
// some other methods.
return "";
}
private void prepareUpdateConfigurationRequest() {
implPutCustomerProductOrderIdProductConfigurationsImpl.setReq(getReq());
implPutCustomerProductOrderIdProductConfigurationsImpl.setUriInfo(getUriInfo());
}}
// Test class using Mockito Framework
#RunWith(MockitoJUnitRunner.class)
public class CTest {
#Mock
private A a = Mockito.mock(A.class);
#InjectMocks
private C c = new C();
private ImplBackEndInput implBackEndInput;
#Test
public void testExecuteCallObject() {
implBackEndInput = new ImplBackEndInput();
UriInfo uriInfo = Mockito.mock(UriInfo.class);
Mockito.when(a.getUriInfo()).thenReturn(uriInfo);
Mockito.when(a.getReq()).thenReturn(httpServletRequest);
try {
c.executeCall(implBackEndInput);
} catch (Exception e) {
}
}
}
Protected or privates methods cannot be mocked using Mockito, I would suggest if you are using spring to you create a DummyC class in your test package, reference that as a parent in the springConfig and make it just return the object when is called. In that way the class will use that method as a by-pass to the real class that you don't need to test.
I'm not really sure how your code is compiling, given some static references to non-static methods - A.getUriInfo() - and various other errors. It also doesn't make a whole lot of sense that you're calling setters using getters for the same object:
implPutCustomerProductOrderIdProductConfigurationsImpl.setReq(getReq());
implPutCustomerProductOrderIdProductConfigurationsImpl.setUriInfo(getUriInfo());
But to answer your question for anyone else who might wind up here, you don't need to be mocking type A in the test class at all (here):
Mockito.when(A.getUriInfo()).thenReturn(uriInfo);
Mockito.when(A.getReq()).thenReturn(httpServletRequest);
You really don't need those two lines at all. In fact, you can remove the mock of A entirely (this line): #Mock private A a = Mockito.mock(A.class);
Instead, just do:
c.setUriInfo(uriInfo);
c.setReq(httpServletRequest);
This works because C extends A, meaning all of A's methods, when not overridden, are inherited by C. So if you call the non-overridden setter methods on the instance of C, it will go straight to the methods of A. After calling the set methods shown above, when you call c.getUriInfo(), it will return the object you passed in as a parameter to the setUriInfo(uriInfo); method. No need to mock at all here.
I need to run a JUnit vs Spring MVC test case in which preconditions include that certain data is present in the HTTP Session. Most important is that I cannot wire a session-scoped bean: I must access httpServletContext.getSession().
Before showing code, let me explain. The controller I need to test assumes that a certain datum is stored in session, otherwise throws an exception. And that is the correct behaviour for now, because that controller is never invoked without a session and the session is always initialized with application data at login time. And obviously the controller is under security.
In my test, I just need to test whether this controller returns either a redirection or a 404 not found according to the request parameters.
I thought building my test case such as
#Autowired
private HttpServletRequest httpServletRequest;
#Autowired
private ModuleManager moduleManager;
#Autowired
private WebApplicationContext webApplicationContext;
private MenuItem rootMenu;
private MockMvc mockMvc;
#Before
public void setUp() throws Exception
{
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
// No asserzioni
.build();
rootMenu = moduleManager.getRootMenu()
.clone();
httpServletRequest.getSession()
.setAttribute(MenuItem.SESSION_KEY, rootMenu);
assertNotNull(rootMenu.getDescendant(existingSelectedMenu));
assertNull(rootMenu.getDescendant(notExistingMenu));
}
#Test
public void testNavigate() throws Exception
{
mockMvc.perform(get("/common/navigate?target=" + existingSelectedMenu))
.andExpect(status().is3xxRedirection());
assertNotSelected(rootMenu, existingSelectedMenu);
mockMvc.perform(get("/common/navigate?target=" + notExistingMenu))
.andExpect(status().is4xxClientError());
}
Part of the code is truly self-explaining. Anyway I expect /common/navigate to use the value I stored in the session. Like this
#RequestMapping(value = "/common/navigate",
method = RequestMethod.GET)
public String navigate(#RequestParam("target") String target) throws NotFoundException
{
MenuItem rootMenu = (MenuItem) httpServletRequest.getSession()
.getAttribute(MenuItem.SESSION_KEY);
if (rootMenu == null)
throw new RuntimeException("Menu not found in session"); //Never happens
MenuItem menuItem = rootMenu.getAndSelect(target);
if (menuItem == null)
throw new NotFoundException(MenuItem.class, target); //Expected
return "redirect:" + menuItem.getUrl();
}
Now guess. What happens when I run my code?
RuntimeException is thrown in the line I commented as the menu object is not found in the session
Obviously the question is implicit now, but I will still write it: how do I inject data into the Session object so that controllers under test will have them available as precondition?
Found the solution by myself now.
The problem is that the session itself must be mocked too. Spring provides a MockHttpSession class that does the trick. It can be pre-populated with all pre-conditions, but must be passed to every MockMvc request so that the mock will wire the session to the (mocked) servlet context.
Following code initializes the session
mockHttpSession = new MockHttpSession(webApplicationContext.getServletContext());
mockHttpSession.setAttribute(MenuItem.SESSION_KEY, rootMenu);
Following performs the request with mocked session wired to it
mockMvc.perform(get("/common/navigate?target=" + existingSelectedMenu).session(mockHttpSession))
.andExpect(status().is3xxRedirection());
I'm trying to create test cases for a webservice but I'm getting nullpointerexception. This is the web service:
#Path("friendservice")
public class FriendWebService {
private static final Logger logger = Logger.getLogger(FriendWebService.class);
#EJB
private FriendRequestServiceInterface friendRequestService;
#GET
#Path("friendrequest")
#Produces(MediaType.TEXT_PLAIN)
public String createFriendRequest(
#Context HttpServletRequest request) {
logger.info("createFriendRequest called");
String result = "false";
User user = (User) request.getSession().getAttribute("user");
User otherUser = (User) request.getSession().getAttribute("profileuser");
if ((user != null) && (otherUser != null)) {
logger.info("Got two users from session, creating friend request.");
if (friendRequestService.createFriendRequest(user, otherUser)) {
result = "true";
}
}
return result;
}
}
This is my test class:
public class FriendWebServiceTest {
#Mock
FriendRequestServiceInterface FriendRequestService;
#Mock
Logger mockedLogger = mock(Logger.class);
#Mock
HttpServletRequest mockedRequest = mock(HttpServletRequest.class);
#Mock
HttpSession mockedSession = mock(HttpSession.class);
#Mock
User mockedUser = mock(User.class);
#Mock
User mockedOtherUser = mock(User.class);
#InjectMocks
FriendWebService friendWebService = new FriendWebService();
#Before
public void setUp() throws Exception {
}
#Test
public void testCreateFriendRequest() throws Exception {
when(mockedRequest.getSession()).thenReturn(mockedSession);
when(mockedSession.getAttribute("user")).thenReturn(mockedUser);
when(mockedSession.getAttribute("profileuser")).thenReturn(mockedOtherUser);
when(FriendRequestService.createFriendRequest(mockedUser, mockedOtherUser)).thenReturn(true);
assertTrue(friendWebService.createFriendRequest(mockedRequest) == "true");
}
The NullPointerException occurs at "when(FriendRequestService.createFriendRequest(mockedUser, mockedOtherUser)).thenReturn(true);"
What am I doing wrong?
You are chaining method calls on your mocked instance:
#Mock
HttpServletRequest mockedRequest = mock(HttpServletRequest.class);
First of all, you do not need to do both, either use the #Mock annotation or the mock method. Like this, you first assign a Mock and then replace this instance with another mock. I recommend the annotation as it adds some context to the mock such as the field's name. This might already cause your NullPointerException as you however never activate the annotations by calling:
MockitoAnnotations.initMocks(this);
as you do not consequently mock all instances with both measures so far. However, even doing so will further result in your exception, so let's move ahead.
Within friendWebService.createFriendRequest(mockedRequest) you call:
User user = (User) request.getSession().getAttribute("user");
User otherUser = (User) request.getSession().getAttribute("profileuser");
where you call a method on two mocks for which you did not specify any behavior. These mocks do by default return null. You need to specify behavior for this such as:
when(request.getSession()).thenReturn(myMockedSession);
before performing this chained call. Based on this, you can then specify how to react to calls on this mocked instance such as returning your user mocks.
Instead of calling initMocks, You probably need to annotate with #RunWith(MockitoJUnitRunner.class) to your FriendWebServiceTest class.
You can also try adding #RunWith(MockitoJUnitRunner.class) or #ExtendWith(MockitoExtension.class) annotations to your FriendWebServiceTest class for JUnit4 and JUnit5 respectively.
In my RPCServlet I am using the method AbstractRemoteServiceServlet.getThreadLocalRequest() to get the HttpSession. Now I want to unit-test it. I am using Mockito and thought I just could mock everything, but the method is final and protected.
Is there any other way to Unit-test AbstractRemoteServiceServlet.getThreadLocalRequest().getSession()
At the end you are trying to get a Session. In our case we solve this situation doing this:
Using GUICE for getting our instances (making them available in the GIVEN part of the test)
public class TestServerModule extends com.google.inject.AbstractModule {
#Override
protected void configure() {
.....
bind(HttpServletRequest.class).to(MockRequest.class).in(Singleton.class);
bind(HttpServletResponse.class).to(MockResponse.class).in(Singleton.class);
....
}
....
#Provides
#Singleton
RequestUtil getRequestUtil(final HttpServletRequest req, final HttpServletResponse resp) {
return new RequestUtilsImpl() {
public HttpServletRequest getThreadRequest() {
return req;
}
public HttpServletResponse getThreadResponse() {
return resp;
}
};
}
RequestUitl object contains everything related with Session and more server stuff (that is not important for your problem :D). The important part here is you can have access to the getThreadRequest(), so you have access to getSession() method.
What is the problem? You can not have a real HttpServletRequest object in your instances, so you need to mock them. For doing it, we specified the bind rules at the top.
At the end your test should be something like:
#RunWith(...)
#GuiceModules({TestServerModule.class, ....})
public class YourTest extends junit.framework.TestCase {
#Inject RequestUtil requestUtil;
....
#Test public void
test_session_after_doing_something() {
//GIVEN
HttpSession mockedSession = requestUtil.getThreadRequest().getSession();
....
}
....
}