I'm taking Software Testing because I'm majoring in CS. The professor gave us the source code of a program made in Java to test it. I'm testing right now this method:
public static void createPanel(HttpServletRequest req, HttpServletResponse res, HttpSession hs) throws IOException
{
String panelName = req.getParameter("panelName");
String panelDescription = req.getParameter("panelDescription");
int employeeID = ((EmployeeProfile)hs.getAttribute("User Profile")).EmployeeID;
boolean result;
//Let's validate our fields
if(panelName.equals("") || panelDescription.equals(""))
result = false;
else
result = DBManager.createPanel(panelName, panelDescription, employeeID);
b = result;
//We'll now display a message indicating the success of the operation to the user
if(result)
res.sendRedirect("messagePage?messageCode=Panel has been successfully created.");
else
res.sendRedirect("errorPage?errorCode=There was an error creating the panel. Please try again.");
}
I'm using Eclipse with JUnit and mockito to test all the methods including this one. For this specific method, I want to check if the program redirects to one location or another, but I don't know how to do it. Do you have any idea? Thanks.
You can actually achieve it easily with Mockito and ArgumentCaptor:
#RunWith(MockitoJUnitRunner.class)
public class MyTest {
#Mock
private HttpServletResponse response
...
#Test
public void testCreatePanelRedirection(){
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
YourClass.createPanel(request, response, session);
verify(response).sendRedirect(captor.capture());
assertEquals("ExpectedURL", captor.getValue());
}
}
Related
Is there any way to write a mockito test case for the particular case.
public void saveStaffInfo(HttpServletResponse response, RegBean regdata, Staffinfo staffType, boolean status)
throws IOException {
if (status)
{
boolean status1 = staffType.insertlogin(regdata);
if(status1) {
response.sendRedirect("registration.jsp?status=success");
}
else {
response.sendRedirect("registration.jsp?status=login_table_error");
}
} else {
response.sendRedirect("registration.jsp?status=failed");
}
}
I did mock the HttpServeletResponse, RegBean,Staffinfo. However, as it is of void type so I cannot use doReturn().when(mockedMethod).(someMethod). So how do I test these lines?
I also need code coverage. I am very new to this.
The test case
#Test
public void testSaveStaffInfo() throws IOException, ServletException{
boolean status =true;
// System.out.println(iStaffInfo.insertlogin(regdata));
Mockito.when(iStaffInfo.insertlogin(regdata)).thenReturn(Boolean.TRUE );
reg.saveStaffInfo(response, regdata, iStaffInfo,status);
}
You need to think what it is you want to test here. What is the "output"? The "output" here is that the method is doing something to your HttpServletResponse, it is calling sendRedirect.
You can verify that certain methods are being called on your mocked (or real) objects with Mockito.verify
I have an HTTPClient test for my spring boot app. I have a class that throws an exception if the a POST request to the server is in a string 2048 bytes or over.
#Component
public class ApplicationRequestSizeLimitFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
System.out.println(request.getContentLength());
if (request.getContentLengthLong() >= 2048) {
throw new IOException("Request content exceeded limit of 2048 bytes");
}
filterChain.doFilter(request, response);
}
}
I created a unit test for it but I am not sure how I can write an assert statement to check if it fails to post the request.
Right now I have this so far in my test class
#Test
public void testSize() throws ClientProtocolException, IOException {
Random r = new Random(123);
long start = System.currentTimeMillis();
String s = "";
for (int i = 0; i < 65536; i++)
s += r.nextInt(2);
String result = Request.Post(mockAddress)
.connectTimeout(2000)
.socketTimeout(2000)
.bodyString(s, ContentType.TEXT_PLAIN)
.execute().returnContent().asString();
}
This test fails which is what I want but I want to create an assert so it passes (assert that it fails the http response due to being over the byte limit).
You can surround the failing part with a try/catch, and call fail() at the end of the try block. If an exception is thrown, the fail() instruction should not be reached, and your test should pass.
#Test has an argument to assert that a particular exception gets thrown, you could write your test like e.g :
#Test(expected = IOException.class)
public void testSize() throws ClientProtocolException, IOException {
...
}
There are 3 ways you can achieve that:
1) Use #Test(expected = ....) annotation where you provide class of exception you want to check.
#Test(expected = IOException.class)
public void test() {
//... your test logic
}
This is not a recommended way of exception testing unless your test is really really small and does one thing only. Otherwise, you may get an IOException thrown but you won't be sure which part of test code exactly caused it.
2) Use #Rule annotation with ExpectedException class:
#Rule
public ExpectedException exceptionRule = ExpectedException.none();
#Test
public void testExpectedException() {
exceptionRule.expect(IOException.class);
exceptionRule.expectMessage("Request too big.");
//... rest of your test logic here
}
Please note that exceptionRule has to be public.
3) And last one, quite old-fashioned way:
#Test
public void test() {
try {
// your test logic
fail(); // if we get to that point it means that exception was not thrown, therefore test should fail.
} catch (IOException e) {
// if we get here, test is successfull and code seems to be ok.
}
}
It's an old fashioned way that adds some unnecessary code to your test that is supposed to be clean.
There is another solution, not already presented in these answers, and is my personal preference. assertThatThrownBy
in your case
#Test
public void testSizeException(){
assertThatThrownBy(()-> Request.Post(mockAddress)
.connectTimeout(2000)
.socketTimeout(2000)
.bodyString(s, ContentType.TEXT_PLAIN)
.execute().returnContent().asString())
.isInstanceOf(IOException.class)
.hasMessageContaining("Request content exceeded limit of 2048
bytes");
}
*Disclaimer, above code written directly into SO editor
I have the following problem using Mockito for unit testing:
I have this method:
#Override
public void handle(HttpExchange httpRequest) throws IOException {
Object[] outputResult = processRequest(httpRequest);
String response = (String) outputResult[0];
Integer responseCode = (Integer) outputResult[1];
httpRequest.sendResponseHeaders(responseCode, response.length());
OutputStream os = httpRequest.getResponseBody();
os.write(response.getBytes());
os.close();
}
And I want only to test this method, not the processRequestMethod that is called internally (that I would like to test separately in anthoer test), so I need to mock it and to check at the end of the test that the methods write and close of the OutputStream class have been called.
I have tried two ways, but no luck with none of them:
#Test
public void handleTest() throws IOException {
RequestHandler requestHandler=mock(RequestHandler.class);
String response = "Bad request";
int responseCode = HttpURLConnection.HTTP_BAD_REQUEST;
Object[] result={response,responseCode};
when(requestHandler.processRequest(anyObject())).thenReturn(result);
when (httpExchange.getResponseBody()).thenReturn(outputStream);
requestHandler.handle(httpExchange);
Mockito.verify(outputStream,times(1)).write(anyByte());
Mockito.verify(outputStream,times(1)).close();
}
With the code above, the processRequest method is not called, but neither is the handle method that I want to test, so the test is failing in the line:
Mockito.verify(outputStream,times(1)).write(anyByte());
Saying that this method was not called at all.
However if I add the parameter CALL_REAL_METHODS when creating the mock, like this:
#Test
public void handleTest() throws IOException {
RequestHandler requestHandler=mock(RequestHandler.class,CALLS_REAL_METHODS);
String response = "Bad request";
int responseCode = HttpURLConnection.HTTP_BAD_REQUEST;
Object[] result={response,responseCode};
when(requestHandler.processRequest(anyObject())).thenReturn(result);
when (httpExchange.getResponseBody()).thenReturn(outputStream);
requestHandler.handle(httpExchange);
Mockito.verify(outputStream,times(1)).write(anyByte());
Mockito.verify(outputStream,times(1)).close();
}
Then the processRequest method that I want to skip is actually called when the method executes this line:
when(requestHandler.processRequest(anyObject())).thenReturn(result);
Any clues of what can be wrong?
in your test instead of
RequestHandler requestHandler=mock(RequestHandler.class,CALLS_REAL_METHODS);
use Mockito.spy():
RequestHandler requestHandler=spy(RequestHandler.class);
doReturn(result).when(requestHandler).processRequest(httpRequest);
you may want the doReturn().when() form rather than the when().thenReturn() because the first does not execute the method whereas the latter does.
On the other hand I'd prefer to move processRequest() to another class where you can inject an instance of into RequestHandler which would make mocking more straight...
The following code is my sample servlet application
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String userEmail = request.getPathInfo().split("/")[1];
saveEmails(response, userEmail);
}
protected void saveEmails(HttpServletResponse response, String email) {
ArrayList<String> userEmails = (ArrayList<String>)getServletContext().getAttribute("userEmails");
if (userEmails == null) {
System.out.println("creating a new linked list");
ArrayList<String> newUserEmails = new ArrayList<String>();
newUserEmails.add(email);
getServletContext().setAttribute("userEmails", newUserEmails);
} else {
System.out.println("appending new email into linked list");
getServletContext().setAttribute("userEmails", userEmails.add(email));
}
System.out.println(userEmails);
}
Whenever I make the first (localhost/value1) and second (localhost/value2) requests it (getServletContext().getAttribute("userEmails")) prints out the following
[value1]
[value1,value2]
However whenever I make the third (localhost/value3) request it always converts LinkedList into boolean and prints out the following error
HTTP Status 500 - java.lang.Boolean cannot be cast to java.util.LinkedList
I'm not sure what's going on, do I need to configure something in my web.xml?
List.add() returns a boolean, so on the second time when you call userEmails.add(email) the attribute is replaced by a Boolean.
You don't need to keep setting the attribute after you've put it in the context the first time (unless you want to replace the whole list). Just replace
getServletContext().setAttribute("userEmails", userEmails.add(email));
with
userEmails.add(email);
I am trying to add a restful api to a java microservice. For this, I am using spark:
http://sparkjava.com/documentation.html
I've created a very simple class which stands up an api. That class is here:
public class Routes {
public void establishRoutes(){
get("/test", (req, res) -> "Hello World");
after((req, res) -> {
res.type("application/json");
});
exception(IllegalArgumentException.class, (e, req, res) -> {
res.status(400);
});
}
Now, running Routes.establishRoutes() should stand up an api which would show "Hello World" in the event someone decides to visit http://localhost:4567/test. This does actually work. Hurray!
The next step is unit testing the code. My unit test, unfortunately, does not succeed. The spark documentation does not detail a sound way for doing testing so what I have is pieced together from examples I found around the net. Here is my Junit test:
public class TestRoutes {
#Before
public void setUp() throws Exception {
Routes newRoutes = new Routes();
newRoutes.establishRoutes();
}
#After
public void tearDown() throws Exception {
stop();
}
#Test
public void testModelObjectsPOST(){
String testUrl = "/test";
ApiTestUtils.TestResponse res = ApiTestUtils.request("GET", testUrl, null);
Map<String, String> json = res.json();
assertEquals(201, res.status);
}
Here is the code behind ApiTestUtils.request():
public class ApiTestUtils {
public static TestResponse request(String method, String path, String requestBody) {
try {
URL url = new URL("http://localhost:4567" + path);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod(method);
connection.setDoOutput(true);
connection.connect();
String body = IOUtils.toString(connection.getInputStream());
return new TestResponse(connection.getResponseCode(), body);
} catch (IOException e) {
e.printStackTrace();
fail("Sending request failed: " + e.getMessage());
return null;
}
}
public static class TestResponse {
public final String body;
public final int status;
public TestResponse(int status, String body) {
this.status = status;
this.body = body;
}
public Map<String,String> json() {
return new Gson().fromJson(body, HashMap.class);
}
}
}
I am failing on connection.connect() inside ApiTestUtils.request(). Specifically, I get the error: java.lang.AssertionError: Sending request failed: Connection refused
I believe this is happening because the application isn't listening when my test tries to make the request. However, I don't understand why that would be the case. I borrowed the test code from the demo project found here:
https://github.com/mscharhag/blog-examples/blob/master/sparkdemo/src/test/java/com/mscharhag/sparkdemo/UserControllerIntegrationTest.java
UPDATE:
I tried running the example linked above. Turns out, it doesn't work either. Looks like spinning up a spark instance in this context is more difficult than I thought? I'm not trying to figure out how to do so.
In your test case is missing the code used for waiting the initialization of the embedded server.
I've tried your code and stumbled on the same issue as you did, but after debugging it I've noticed that the embedded spark server is initialized in a newly created thread. ( see the method spark.Service#init()).
All you need to do in your test is to await for the initialization by calling the method spark.Spark#awaitInitialization()
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static junit.framework.TestCase.assertEquals;
import static spark.Spark.awaitInitialization;
import static spark.Spark.stop;
public class TestRoutes {
#Before
public void setUp() throws Exception {
Routes newRoutes = new Routes();
newRoutes.establishRoutes();
awaitInitialization();
}
#After
public void tearDown() throws Exception {
stop();
}
#Test
public void testModelObjectsPOST() {
String testUrl = "/test";
ApiTestUtils.TestResponse res = ApiTestUtils.request("GET", testUrl, null);
assertEquals(200, res.status);
}
}
I can't help you with Spark, but if you're open to trying an alternative lightweight Java library for writing micro services, have a look at Molecule.
You'll find documentation and examples for writing unit tests and integration tests. If I understand what you're trying to test correctly, the test would look like:
HttpRequest request = new HttpRequest(4567);
HttpResponse response = request.get("/test");
assertThat(response).hasStatusCode(201)
.hasContentType("application/json")
.hasBodyText("Hello World");