I have a Ajax call sent from browser to a Servlet. At Servlet some value is calculated say A. My query is how can I validate this A. I am using TestNG from where the browser starts but after that control shifts to Servlet. How should I return the value from Servlet such that in TestNG I can fetch it and validate.
solutions I can think of:
(1)
Bypass the servlet: put your business calculations in a separate method/class, and test directly. This might be enough if the focus is on the business code (while the servlet layer does trivial tasks such as extracting simple request parameters). E.g:
// logic - assuming this is the test focus, with interesting cases such as insufficient funds, limited account etc.
public class MyBank{
public void transferFunds(int fromAccountId, int toAccountId, int dollars)...
}
// servlet that happens to have trivial code that isn't so important to test
public class MyServlet{
...
int fromAccountId=Integer.parseInt(req.getParameter("fromAccountId"));
int toAccountId=Integer.parseInt(req.getParameter("toAccountId"));
int dollars= Integer.parseInt(req.getParameter("dollars"));
bank.transferFunds(fromAccountId, toAccountId, dollars)
}
(2) Use an embedded server, like Jetty.
http://www.eclipse.org/jetty/documentation/current/embedding-jetty.html
From your unit test you just launch a jetty (using 'new Server()'...) and tell it to execute the servlet.
(3) you can also invoke your servlet, injecting it with mock request/response/session etc. Spring, for example, has such mock objects.
So it's something like:
HttpServletRequest mockReq=new MockHttpServletRequest();
HttpServletRequest mockResp=new MockHttpServletResponse();
new MyServlet().service(mockReq, mockResp);
Just note it might require some tweaking depending on what your servlet needs - e.g. request parameters, session (the mock request has methods to add them)
Related
I've been tasked with creating a simple REST API, where a single double is provided, and another one is derived from it according to some rules.
When creating a controller, I made the method for parsing said base double in two ways.
#GetMapping("calculate/{income:.+}")
public ResponseEntity<?> calculateEAT(#PathVariable double income){
return ResponseEntity.ok(TaxDAO.addResult(income));
}
#PostMapping("calculate/{income:.+}")
public ResponseEntity<?> calculateEAT(#PathVariable double income){
return ResponseEntity.ok(TaxDAO.addResult(income));
}
The only difference is the type of mapping used. The only difference I noticed was that I could type income in the browser address bar with GET mapping - and it worked. With post mapping, I could only get results using Postman.
I'm assuming it's possible to write an entire controller using GET mapping. I don't really feel like it's a good practice though. Are there any rules for using Request Methods in controllers?
GET and POST requests are different HTTP methods. The browser will do a GET request when you type something in the browser address bar, that is why you can only make it work in Postman (where you can select which HTTP method to use).
You should use GET when you want to retrieve something from the REST API. You should use POST when you want to submit something to the REST API, usually creating a resource or triggering some kind of process. You can read more about each HTTP method in the following online resources:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods
https://www.restapitutorial.com/lessons/httpmethods.html
We have a Spring MVC webapp, and we're currently able to unit test the controllers with MockHttpServletRequest objects.
Our tests look similar to:
request = new MockHttpServletRequest(_mockServletContext, "PUT", "/createNewUser.action");
request.setParameter("username", "bob123");
response = new MockHttpServletResponse();
userController.createNewUser(request, response);
// Ensure the user was created, etc.
Then, we query the underlying database (and other controllers) to ensure that things worked properly.
However, this does not test the actual JSP pages that we're shipping. Just the fair-weather mocked request.
What we would like to accomplish, is being able to mock the entire process from the perspective of an actual user viewing the page in a browser, like:
request = new MockHttpServletRequest(_mockServletContext, "GET", "/newUser.html");
response = new MockHttpServletResponse();
userController.newUser(request, response);
//Pseudo-code!
DOM thePage = SomeBuilder.fromResponse(response);
thePage.getTextField("usernameField").setText("bob123");
thePage.getButton("submitUserButton").click();
// Then, we test the same assertions
...
This helps us establish unit tests based on the view as the client will actually see it, and would involve ensuring that the proper HTML components exist, and the Javascript backing the button click is also sending the proper parameters to the server/controller, in the event it someday requires a user's first name, for example. Or, in the case there is a typo and the HTML form actually sends the parameter "userUsername" instead of "username". We'd like to remove the manual testing requirement in this case, as there are different code paths/form layouts depending on the role of the currently-authenticated user.
Are there Java/Spring MVC based unit testing frameworks to accomplish this task? Or other code patterns that would provide similar reliability?
My understanding is that the GWT RequestFactory (RF) API is for building data-oriented services whereby a client-side entity can communicate directly with it's server-side DAO.
My understanding is that when you fire a RF method from the client-side, a RequestFactoryServlet living on the server is what first receives the request. This servlet acts like a DispatchServlet and routes the request on to the correct service, which is tied to a single entity (model) in the data store.
I'm used to writing servlets that might pass the request on to some business logic (like an EJB), and then compute some response to send back. This might be a JSP view, some complicated JSON (Jackson) object, or anything else.
In all the RF examples, I see no such existence of these servlets, and I'm wondering if they even exist in GWT-RF land. If the RequestFactoryServlet is automagically routing requests to the correct DAO and method, and the DAO method is what is returned in the response, then I can see a scenario where GWT RF doesn't even utilize traditional servlets. (1) Is this the case?
Regardless, there are times in my GWT application where I want to hit a specific url, such as http://www.example.com?foo=bar. (2) Can I use RF for this, and if so, how?
I think if I could see two specific examples, side-by-side of GWT RF in action, I'd be able to connect all the dots:
Scenario #1 : I have a Person entity with methods like isHappy(), isSad(), etc. that would require interaction with a server-side DAO; and
Scenario #2 : I want to fire an HTTP request to http://www.example.com?foo=bar and manually inspect the HTTP response
If it's possible to accomplish both with the RF API, that would be my first preference. If the latter scenario can't be accomplished with RF, then please explain why and what is the GWT-preferred alternative. Thanks in advance!
1.- Request factory not only works for Entities but Services, so you could define any service in server-side with methods which you call from client. Of course when you use RF services they are able to deal with certain types (primitive, boxed primitives, sets, lists and RF proxies)
#Service(value=RfService.class, locator=RfServiceLocator.class)
public interface TwService extends RequestContext {
Request<String> parse(String value);
}
public class RfService {
public String parse(String value) {
return value.replace("a", "b");
}
2.- RF is not thought to receive other message payloads than the RF servlet produces, and the most you can do in client side with RF is ask for that services hosted in a different site (when you deploy your server and client sides in different hosts).
You can use other mechanisms in gwt world to get data from other urls, take a look to gwtquery Ajax and data-binding or this article
I've a third-party servlet inside a JAR that I cannot change. I've extended that servlet and been using it normally as a servlet should be used, the client side makes an HTTP request that invokes my servlet.
But now the client wants an automatic service, that is, I will need to do some requests to that third party servlet from the same webapp where the servlet is.
I looked at the the third party servlet code but I didn't found a place to bypass the servlet because the HttpServletRequest and HttpServletResponse objects are passed from method to method... Basically it seems that I would need to re-implement all the third party code.
Solutions I found but do not satisfy me:
Call servlet from URL with HttpURLConnection: My common sense says that calling the third party servlet from a url is not the best way to
go, besides the overhead added, I don't want to expose the third party
servlet. Calling my servlet from a url also brings problems with
sessions and other things.
Call the doGet directly: This seems to be out of the question because there is no implementation for the HttpServletRequest and
HttpServletResponse.
Use jMock or something like that: Didn't explore this solution yet, but it seams wrong to use a test-driven library in the real
environment.
Anyone has an idea how to interact with that third party servlet?
EDIT:
Since my English is not very good and I'm finding difficult to explain myself here goes a schematic to try to explain better
EDIT2: After a meeting the third party maker they offer to isolate the methods I need to avoid calling the servlet. If you don't have the same luck I did check out both gigadot and BalusC answers.
If I understand your question correctly, you have implemented or have a third party servlet that generate the report for you.
Now what you want to do is to periodically generate the report and store in session so that when user want to get the report they can retrieve it using another servlet.
If this is the case then you want the task to be running periodically on your server. You will need some sort of task scheduler to run on your server and what the task does is just make a http request to your servlet (this can be http GET or POST).
Calling my servlet from a url also brings problems with sessions and other things.
If that's the sole problem, then just use the CookieManager to maintain the cookies (and thus also the session) in subsequent URLConnection calls.
// First set the default cookie manager.
CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));
// All the following subsequent URLConnections will use the same cookie manager.
URLConnection connection = new URL(url).openConnection();
// ...
connection = new URL(url).openConnection();
// ...
connection = new URL(url).openConnection();
// ...
See also:
Using java.net.URLConnection to fire and handle HTTP requests
You could try to separate out your servlet logic into several phases. The entry point that takes the request/result, the action that processes parameters sent and generates the output.
public void doGet(HttpServletRequest req, HttpServletResponse rsp){
relay(rsp,act(req.getParameter("a"));
}
public static String act(String a){
return "You provided: " + a;
}
public static void relay(HttpServletResponse rsp, String content){
rsp.setResponseCode(200);
rsp.getOutputStream().write(content.getBytes());
}
This lets you call act(whatever) to do what you want, and then do what you want with the response. If returning a string is not enough, you could make any return type you want, probably something that could contain a list of headers, response code, and content template.
Since you guys have been very helpful in my early steps into the Play Framework (thanks for that), here it goes again:
We have a working registration controller, that POSTS all credentials to the database.
But then, we want to make it possible to be immeadiately logged in afterwards. Below is the code that makes this work:
public static void doRegistration(#Valid User user) {
//registering the user
try{
SecureController.authenticate(user.username, user.password, false, "MainController.index");
}catch(Throwable ex){
MainController.index();
}
This works fine, but it is not very safe because it GETs all the credentials to the server. I know I have to edit my routes file somehow, but I can't see how.
The routes file:
* /account SecureController.login
POST /account/register RegistrationController.doRegistration
GET /account/register SecureController.login
Somewhere should be the action SecureController.authenticate, but what do I have to put in the column after the POST... It can't be /account/register, because that fails...
Thank you beforehand!
I am not sure I understand your issue. The routes file is just a way to configure your URLs to be pretty URLs. If you don't specify them, then it falls back on default {controller}/{method} syntax.
The issue you are having, is that when you call another controller Play performs a redirect to that controller's method, which involves sending a request back to your browser telling it to redirect (this ensures that the state of the application is reflected in the URL within the browser). A redirect needs therefore to send a GET request, and included in the GET request will be your parameters.
what you are trying to do, as you said, is not safe. What you should do (not the only option, only one possibility) is:
Maintain your current doRegistration action for the user
Create a service class (that does not inherit Controller). It can be static or require instantiation (with static methods should be enough though).
Add a #Before method to a common controller that will be executed always. One way is to create a controller with a #Before method and add this controller to all other controllers via the #With annotation, so that #Before will be executed always for all controllers. It requires you to add a #With to each new controller, but I believe it keeps the code quite clean.
The idea would be that the controller calls the authenticate method from the service class. It's a simple static This method checks the user (if it's enabled, has proper license, whatever) and sets some parameters in the session (via Session object).
To help with this you may want to create another authenticate method in the user that returns the attributes to set (for example in a Map, if it contains an "error" key the user can't be authenticated for some reason). How to do this step can change according to your requirements.
Once the Session has been set, you redirect to the page of your election (main, profile, etc). As you have the common #Before method, this will be executed. This method should verify the credentials in the session (user authenticated, license type, etc) and act accordingly. You have an example in the Secure controller of Play, but you could create your own.
With this, you could user the authenticate method of the service from any controller, allowing authentication via multiple methods, and using a common point to verify the session.