This week's giveaway is in the Android forum.
We're giving away four copies of Android Security Essentials Live Lessons and have Godfrey Nolan on-line!
See this thread for details.
The moose likes Testing and the fly likes Unit Test a Servlet Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Android Security Essentials Live Lessons this week in the Android forum!
JavaRanch » Java Forums » Engineering » Testing
Bookmark "Unit Test a Servlet" Watch "Unit Test a Servlet" New topic
Author

Unit Test a Servlet

Sidd Joshi
Greenhorn

Joined: May 05, 2014
Posts: 3
Hello,

Can anyone please help me with how to unit test a servlet which has few private final variables/instances. These instances/variables have to be final across the servlet since they cause an issue of mutable servlet fields(as identified by findbugs plugin) if they are not final.

Code works fine, but serious issue that I am facing right now is to Unit test the servlet.
I am trying to mock the request, response object but still of no use. As you cannot set the values to the final instances/variables of servlet class.

Can anyone help me with this?
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4167
    
  21

Perhaps you show am example of the class you need to test. It isn't clear to me why you are having problems with final variables.


Steve
Jeanne Boyarsky
internet detective
Marshal

Joined: May 26, 2003
Posts: 30123
    
150

Welcome to CodeRanch!

What are the types of those final objects?


[Blog] [JavaRanch FAQ] [How To Ask Questions The Smart Way] [Book Promos]
Blogging on Certs: SCEA Part 1, Part 2 & 3, Core Spring 3, OCAJP, OCPJP beta, TOGAF part 1 and part 2
Sidd Joshi
Greenhorn

Joined: May 05, 2014
Posts: 3
Steve Luke wrote:Perhaps you show am example of the class you need to test. It isn't clear to me why you are having problems with final variables.


import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;



import org.springframework.context.support.ClassPathXmlApplicationContext;

// few import statements specific to my task

/**
* Handles user information and redirects based on user input validations.
*/
public class SignUpServlet extends HttpServlet {

/**
* Generated SerialVersionUID.
*/
private static final long serialVersionUID = 2303428554104148740L;
private transient final ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(
"config/BeanLocations.xml");
private transient final ValidatorImpl validator = (ValidatorImpl) appContext.getBean("welcomeValidator");

/**
* {@inheritDoc} Receives user information and based on the input
* validations status, redirects to the respective page.
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, java.io.IOException {
try {
Map<String, String[]> userInformation = new HashMap<String, String[]>();
userInformation = request.getParameterMap();
SimulatorDao simulator = (SimulatorDao) appContext.getBean("simulatorDao");
if ((isFormInValid("firstName", userInformation, request)
|| isFormInValid("lastName", userInformation, request)
|| isFormInValid("teamName", userInformation, request)
|| isFormInValid("userName", userInformation, request)
|| isFormInValid("password", userInformation, request)
|| isFormInValid("roleOptions", userInformation, request))
|| userNameAlreadyExists("userName", userInformation, request)) {
request.getRequestDispatcher("SignUpPage.jsp")
.forward(request, response);
return;
}

//checks whether the User information is successfully stored into database. If yes returns true.
if (UserInformationSetup.successfulRegistration(simulator,
userInformation)){
request.getRequestDispatcher("Success.jsp").forward(request,
response);
}
else{
request.getRequestDispatcher("ErrorPage.jsp")
.forward(request, response);
}

} catch (Exception e) {
e.printStackTrace();
}
}

/**
* Returns boolean status for input value and sets error msg to request
* attribute.
*
* @param paramName Input field Name.
* @param userInformation User details entered through form.
* @param req Http request object.
* @return status returns false if validation is success, else returns true when validation is unsuccessful.
*/
private boolean isFormInValid(String paramName,
Map<String, String[]> userInformation, HttpServletRequest req) {
boolean status = false;

// does something - calling validation methods to validate and sets status to either true or false depending upon validation.
}
}
return status;
}

/**
* Checks if the User Name is already registered, if exists returns true and sets attribute, default is false.
*
* @param paramName User Name provided by user.
* @param userInformation User details entered through the form.
* @param requestObject Http request object
* @return returns false if name doesn't exist in the database, else returns true if name already registered/exists.
*/

private boolean userNameAlreadyExists(String paramName, Map<String, String[]> userInformation, HttpServletRequest requestObject){
boolean existenceStatus = false;
{
//calls the method which checks if name exists in database, if exists returns true else false.
}
return existenceStatus;
}
}


The concern that I have is, I am instantiating beans - simulator, validator through appContext(Using dependency injection). In order to test i need to mock appContext, simulator. But these are final and i cannot reassign values into these objects/instances.
Jeanne Boyarsky
internet detective
Marshal

Joined: May 26, 2003
Posts: 30123
    
150

I'd remove the final modifier and suppress the error in findbugs. The modifier only exists to make findbugs happy. You can change the value of what is in that context all you want anyway so it isn't really final. Or better yet, move them to a helper class so they aren't in the servlet at all.



That said, if you want to leave it as final, you could still test it with something like this:


Sidd Joshi
Greenhorn

Joined: May 05, 2014
Posts: 3
Thank you for the reply,

In the first place, I have to use FindBugs in my project and cannot suppress/ignore the warnings generated by findbugs.

In the second case, In order to accommodate testing, are we suppose to write the code/add code in the class under test? In my case I cannot do this, is there an alternative approach to this issue?
Jeanne Boyarsky
internet detective
Marshal

Joined: May 26, 2003
Posts: 30123
    
150

Sidd Joshi wrote:In the first place, I have to use FindBugs in my project and cannot suppress/ignore the warnings generated by findbugs.

What if they are wrong? That isn't the case here, but sometimes static analysis engines give false positives. In this case, I agree with FindBugs - having a final (or any variable of this sort) in a servlet is not a good idea.

Sidd Joshi wrote:In the second case, In order to accommodate testing, are we suppose to write the code/add code in the class under test? In my case I cannot do this, is there an alternative approach to this issue?

Yes. Refactoring code to make it unit testable is a common practice. There is even a book on it "Working Effectively with Legacy Code"

Sidd Joshi wrote:In my case I cannot do this, is there an alternative approach to this issue?

Why not? Without knowing why this is infeasible, we can't suggest more alternatives.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Unit Test a Servlet
 
Similar Threads
junits..
Compile time constant
Servlets and Singleton
Unit Testing and Accessing Private Methods and Instance Variables
thread safe