How to pass request for a delete method in junit - junit

Hi I have a json request which I have to pass in my junit testcase but the request is delete as delete do not support setEntity method. How can I pass the request in my testcase.
Json request which I have to pass
{
"userId":"AJudd",
"siteId":"131",
"alternateSiteId":"186"
}
mytest case for this
#Test
public void testdeleteAltSite() throws ClientProtocolException, IOException {
String resultCode = "001";
String resultText = "Success";
String url = "http://localhost:8080/adminrest1/alternatesite";
HttpClient client = HttpClientBuilder.create().build();
HttpDelete delete = new HttpDelete(url);
// add header
delete.addHeader("Transaction-Id", "11");
delete.addHeader("content-type", "application/json");
LOG.info(url);
HttpResponse response = client.execute(delete);
byte[] buf = new byte[512];
InputStream is = response.getEntity().getContent();
int count = 0;
StringBuilder builder = new StringBuilder(1024);
while ((count = is.read(buf, 0, 512)) > 0) {
builder.append(new String(buf, 0, count));
}
String output = builder.toString();
System.out.println(output);
}`
How to pass the json value so that the passed value data can be deleted?

IMHO this is a problem with your design.
If your intent is to delete an alternate site and its id is unique then passing the alternateSiteId as part of the URI should sufficient:
Method: DELETE
URL: http://localhost:8080/adminrest1/alternatesite/{alternateSiteId}
If alternateSiteId is not unique then you are updating a relationship. In that case you should use a PUT which allows you to include a body in your request. Please note you should pass the id of the resource you are updating as part of your URI, for example:
Method: PUT
URL: http://localhost:8080/adminrest1/alternatesite/{userId}
Body:{
"siteId":"131",
"alternateSiteId":"186"
}

Ok, first of all: Sending a body with a DELETE is not what usually happens around the internet. Nevertheless, it is not forbidden (Is an entity body allowed for an HTTP DELETE request?). So, two ideas:
1) New class
I assume you use org.apache.http.client: Just extend HttpEntityEnclosingRequestBase:
public class HttpDeleteWithEntity extends HttpEntityEnclosingRequestBase {
public final static String METHOD_NAME = "DELETE";
public HttpDeleteWithEntity() {
super();
}
public HttpDeleteWithEntity(final URI uri) {
super();
setURI(uri);
}
public HttpDeleteWithEntity(final String uri) {
super();
setURI(URI.create(uri));
}
#Override
public String getMethod() {
return METHOD_NAME;
}
}
This is basically c&p'ed from the HttpPost class. I did not test this, tho.
Then use your HttpDeleteWithEntity class instead of HttpDelete.
2) Use custom headers
If you can modify your server code that might be a good alternative.
delete.addHeader("testwith", jsonString);
or
delete.addHeader("userId","AJudd");
delete.addHeader("siteId","131");
delete.addHeader("alternateSiteId","186);
Finally, if you are in charge of the server implementation I would recommend to implement DELETE requests without any body (see artemisian's answer).

Related

ASP.NET MVC DataBinder not deserializing simple types from JSON

Input JSON:
{ "name": "gerry" }
Action method:
{ public ActionResult GenerateQrCode([FromBody] string name }
Problem:
The simple-type args are null
ModelState: Invalid
The built-in json deserializer can't handle the input in this form
I've tried:
ConfigureServices() -> services.AddControllersWithViews().AddNewtonsoftJson(); to switch to NewtonSoft, which I know/love
I've set a break-point into the non-NewtonSoft built-in MS SystemTextJsonInputFormatter.ctor() just to check, if it's still used: yes, it is, I'm not sure why, when I'm calling the above .AddNewtonsoftJson()
The situation:
The client POSTs all the input params as one JSON string document, which is UTF8 w/out BOM
The string comes in at the server-side and is nicely readable with new System.IO.StreamReader(Request.Body).ReadToEnd() from inside the immediate window
I need a way ASP.NET Core deserializes this, as it was able under the .NET4.X for many years w/out any issue
I wouldn't like to add [FromBody] and similar opt-in signatures all over the server actions/args
You pass the name as json but accept as a string so it will be null, you can use an InputFormatter like:
public class RawJsonBodyInputFormatter : InputFormatter
{
public RawJsonBodyInputFormatter()
{
this.SupportedMediaTypes.Add("application/json");
}
public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)
{
var request = context.HttpContext.Request;
using (var reader = new StreamReader(request.Body))
{
var content = await reader.ReadToEndAsync();
return await InputFormatterResult.SuccessAsync(content);
}
}
protected override bool CanReadType(Type type)
{
return type == typeof(string);
}
}
In startup.cs:
services
.AddMvc(options =>
{
options.InputFormatters.Insert(0, new RawJsonBodyInputFormatter());
});
And then you can get the row string
To deserilize it, you can check this, use Newtonsoft and make the string to a Model
[HttpPost]
public IActionResult GenerateQrCode([FromBody] string name)
{
object o = JsonConvert.DeserializeObject(name);
MyModel my = JsonConvert.DeserializeObject<MyModel>(o.ToString());
return View();
}

Forward JSON POST request from one REST API to another

I have the following situation:
My REST API one:
#RestController
#RequestMapping("/controller1")
Public Class Controller1{
#RequestMapping(method = RequestMethod.POST)
public void process(#RequestBody String jsonString) throws InterruptedException, ExecutionException
{
............
}
}
JSON POST request, request1, for the REST API(Controller1):
{
"key1":"value1",
"key2":"value2"
}
My REST API two:
#RestController
#RequestMapping("/controller2")
Public Class Controller2{
#RequestMapping(method = RequestMethod.POST)
public void process(#RequestBody String jsonString) throws InterruptedException, ExecutionException
{
............
}
}
JSON request, request2, for the REST API(Controller2):
{
"key1":"value1",
"key2":"value2",
"key3":"value3"
}
I have several such "primitive" requests.
Now, I am expecting a JSON request, let's call it request3, which is a combination of such "primitive" queries- something that looks like below:
{
{
"requestType":"requestType1",
"request":"[{"key1":"value1","key2":"value2"}]"
},
{
"requestType":"requestType2",
"request":"[{"key1":"value1","key2":"value2","key3":"value3"}]"
}
}
Here, I need to trigger the respective API (one or two) upon identifying the query type. I wanna know how I can forward the request to the corresponding REST API. I wrote the REST API for request3 like below:
#RestController
#RequestMapping("/controller3")
Public Class Controller3{
#RequestMapping(method = RequestMethod.POST)
public void process(#RequestBody String jsonString) throws InterruptedException, ExecutionException
{
..................
..................
switch(request){
case request1: //how to call REST API 1?
case request2: //how to call REST API 2?
}
}
}
You can call a utility method which posts request to controller using Rest Template as below. Since you are using POST method it's easy to send parameters using Rest Template. You may need to edit this code a bit to work in your environment with exact syntax.
#RequestMapping( value= "/controller3" method = RequestMethod.POST)
public #ResponseBody void process(#RequestBody String jsonString){
String request = requestType //Get the request type from request
String url = "";
MultiValueMap<String, String> params= null;
switch(request){
case request1: //how to call REST API 1?
url = "/controller1";
params = request1param //Get the parameter map from request
case request2: //how to call REST API 2?
url = "/controller2";
params = request2Param //Get the parameter map from request
}
//Now call the method with parameters
getRESTResponse(url, params);
}
private String getRESTResponse(String url, MultiValueMap<String, String> params){
RestTemplate template = new RestTemplate();
HttpEntity<MultiValueMap<String, String>> requestEntity=
new HttpEntity<MultiValueMap<String, String>>(params);
String response = "";
try{
String responseEntity = template.exchange(url, HttpMethod.POST, requestEntity, String.class);
response = responseEntity.getBody();
}
catch(Exception e){
response = e.getMessage();
}
return response;
}
Redirect from one controller method to another controller method
Alternatively you also can call the rest method using Rest Template
Spring MVC - Calling a rest service from inside another rest service
You may find how to send POST request with params in this post
https://techie-mixture.blogspot.com/2016/07/spring-rest-template-sending-post.html

Can't read Mocked Java.io.Reader

I want to test following code with Mockito:
public static String funcToTest(String query) throws Exception {
String url = Config.getURL(serviceName);
HttpClient client = new HttpClient();
HttpMethod method = new GetMethod(url);
String resultantString= "";
method.setQueryString(URIUtil.encodeQuery(query));
client.executeMethod(method);
if (method.getStatusCode() == HttpStatus.SC_OK) {
Reader reader = new InputStreamReader(method
.getResponseBodyAsStream());
int charValue = 0;
StringBuffer sb = new StringBuffer(1024);
while ((charValue = reader.read()) != -1) {
sb.append((char) charValue);
}
resultantString = sb.toString();
}
method.releaseConnection();
return resultantString;
}
I created the test like following:
#Test
public void testFunc() throws Exception{
HttpMethod method = Mockito.mock(HttpMethod.class);
InputStream inputStream = Mockito.mock(InputStream.class);
Reader reader = Mockito.mock(Reader.class);
when(method.getResponseBodyAsStream()).thenReturn(inputStream);
PowerMockito.whenNew(Reader.class).withArguments(eq(inputStream)).thenReturn(reader);
Mockito.when(reader.read()).thenReturn((int)'1', -1);
String actualResult = cls.funcToTest("");
String expected = "1";
assertEquals(expected, actualResult);
}
But the reader.read() method is not returning 1. Instead it always returns -1. How should I mock Reader so that read() method will return something else other than -1.
Thanks.
First of all , your test code is doing lots of .class mocking to mock function local variables / references. Mocking is for class dependencies and not for function local variables.
As written, you can't test your function funcToTest with mocking alone. You need to rewrite this function if not willing to use real objects for - HttpMethod & Reader.
You need to remove object creation code with new outside this function if you wish to mock calls on those objects and replace code of new with this get method. e.g.
protected HttpMethod getHttpMethod(String Url){
return new GetMethod(url);
}
Also, I don't see you mocking this line for a fake URL - it seems necessary for unit testing.
String url = Config.getURL(serviceName);
After taking object creation code outside your function, you need to create a new class than extends your SUT ( Subject Under Test ) and you override these methods ( getHttpMethod) to provide fake/mocked instances.
You need to write similar method to get Reader instance.
Then you test this new class - extended from your SUT since object creation logic need not to be tested.
Without taking object creation code outside the function, I don't see a way of mocking it by mockito.
Hope it helps !!
It must work, I'm sorry what make you slightly confused )
// annotations is very important, cls I your tested class name, i assume cls is yours
#RunWith(PowerMockRunner.class)
#PrepareForTest({cls.class})
public class PrinterTest {
#Test
public void print() throws Exception {
String url = "";
GetMethod method = Mockito.mock(GetMethod.class);
InputStream inputStream = Mockito.mock(InputStream.class);
InputStreamReader reader = Mockito.mock(InputStreamReader.class);
Mockito.when(method.getResponseBodyAsStream()).thenReturn(inputStream);
//forgot about it )
PowerMockito.whenNew(GetMethod.class).withArguments(eq(url)).thenReturn(method);
PowerMockito.whenNew(InputStreamReader.class).withArguments(eq(inputStream)).thenReturn(reader);
Mockito.when(reader.read()).thenReturn((int) '1', -1);
when(method.getStatusCode()).thenReturn(HttpStatus.SC_OK);
String actualResult = cls.funcToTest(url);
String expected = "1";
assertEquals(expected, actualResult);
}
}

Struts2 Convert json array to java object array - not LinkedHashmap

First off my question is very similar to below however I'm not sure if the answers are applicable to my specific problem or whether I just need clarification about how to approach it:
Convert LinkedHashMap<String,String> to an object in Java
I am using struts2 json rest plugin to convert a json array into a java array. The array is sent through an ajax post request and the java receives this data. However instead of being the object type I expect it is received as a LinkedHashmap. Which is identical to the json request in structure.
[
{advance_Or_Premium=10000, available=true},
{advance_Or_Premium=10000, available=true},
{advance_Or_Premium=10000, available=true}
]
The data is all present and correct but just in the wrong type. Ideally I want to send the data in my object type or if this is not possible convert the LinkedHashMap from a list of keys and values into the object array. Here is the class I am using, incoming data is received in the create() method:
#Namespace(value = "/rest")
public class OptionRequestAction extends MadeAbstractAction implements ModelDriven<ArrayList<OptionRequestRest>>
{
private String id;
ArrayList<OptionRequestRest> model = new ArrayList<OptionRequestRest>();
public HttpHeaders create()
{
// TODO - need to use model here but it's a LinkedHashmap
return new DefaultHttpHeaders("create");
}
public String getId()
{
return this.id;
}
public ArrayList<OptionRequestRest> getModel()
{
return this.model;
}
public ArrayList<OptionRequestRest> getOptionRequests()
{
#SuppressWarnings("unchecked")
ArrayList<OptionRequestRest> lReturn = (ArrayList<OptionRequestRest>) this.getSession().get("optionRequest");
return lReturn;
}
// Handles /option-request GET requests
public HttpHeaders index()
{
this.model = this.getOptionRequests();
return new DefaultHttpHeaders("index").lastModified(new Date());
}
public void setId(String pId)
{
this.id = pId;
}
public void setModel(ArrayList<OptionRequestRest> pModel)
{
this.model = pModel;
}
// Handles /option-request/{id} GET requests
public HttpHeaders show()
{
this.model = this.getOptionRequests();
return new DefaultHttpHeaders("show").lastModified(new Date());
}
}
One of the things which is confusing me is that this code works fine and returns the correct object type if the model is not an array. Please let me know if my question is not clear enough and needs additional information. Thanks.

ASP.net MVC returning JSONP

I am looking to return some JSON across domains and I understand that the way to do this is through JSONP rather than pure JSON.
I am using ASP.net MVC so I was thinking about just extending the JsonResult type and then extending the Controller so that it also implemented a Jsonp method.
Is this the best way to go about it or is there a built-in ActionResult that might be better?
Solution: I went ahead and did that. Just for reference sake I added a new result:
public class JsonpResult : System.Web.Mvc.JsonResult
{
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
HttpResponseBase response = context.HttpContext.Response;
if (!String.IsNullOrEmpty(ContentType))
{
response.ContentType = ContentType;
}
else
{
response.ContentType = "application/javascript";
}
if (ContentEncoding != null)
{
response.ContentEncoding = ContentEncoding;
}
if (Data != null)
{
// The JavaScriptSerializer type was marked as obsolete prior to .NET Framework 3.5 SP1
#pragma warning disable 0618
HttpRequestBase request = context.HttpContext.Request;
JavaScriptSerializer serializer = new JavaScriptSerializer();
response.Write(request.Params["jsoncallback"] + "(" + serializer.Serialize(Data) + ")");
#pragma warning restore 0618
}
}
}
and also a couple of methods to a superclass of all my controllers:
protected internal JsonpResult Jsonp(object data)
{
return Jsonp(data, null /* contentType */);
}
protected internal JsonpResult Jsonp(object data, string contentType)
{
return Jsonp(data, contentType, null);
}
protected internal virtual JsonpResult Jsonp(object data, string contentType, Encoding contentEncoding)
{
return new JsonpResult
{
Data = data,
ContentType = contentType,
ContentEncoding = contentEncoding
};
}
Works like a charm.
Here is a simple solution, if you don't want to define an action filter
Client side code using jQuery:
$.ajax("http://www.myserver.com/Home/JsonpCall", { dataType: "jsonp" }).done(function (result) {});
MVC controller action. Returns content result with JavaScript code executing callback function provided with query string. Also sets JavaScript MIME type for response.
public ContentResult JsonpCall(string callback)
{
return Content(String.Format("{0}({1});",
callback,
new JavaScriptSerializer().Serialize(new { a = 1 })),
"application/javascript");
}
Rather than subclassing my controllers with Jsonp() methods, I went the extension method route as it feels a touch cleaner to me. The nice thing about the JsonpResult is that you can test it exactly the same way you would a JsonResult.
I did:
public static class JsonResultExtensions
{
public static JsonpResult ToJsonp(this JsonResult json)
{
return new JsonpResult { ContentEncoding = json.ContentEncoding, ContentType = json.ContentType, Data = json.Data, JsonRequestBehavior = json.JsonRequestBehavior};
}
}
This way you don't have to worry about creating all the different Jsonp() overloads, just convert your JsonResult to a Jsonp one.
Ranju's blog post (aka "This blog post I found") is excellent, and reading it will allow you to further the solution below so that your controller can handle same-domain JSON and cross-domain JSONP requests elegantly in the same controller action without additional code [in the action].
Regardless, for the "give me the code" types, here it is, in case the blog disappears again.
In your controller (this snippet is new/non-blog code):
[AllowCrossSiteJson]
public ActionResult JsonpTime(string callback)
{
string msg = DateTime.UtcNow.ToString("o");
return new JsonpResult
{
Data = (new
{
time = msg
})
};
}
JsonpResult found on
this excellent blog post:
/// <summary>
/// Renders result as JSON and also wraps the JSON in a call
/// to the callback function specified in "JsonpResult.Callback".
/// http://blogorama.nerdworks.in/entry-EnablingJSONPcallsonASPNETMVC.aspx
/// </summary>
public class JsonpResult : JsonResult
{
/// <summary>
/// Gets or sets the javascript callback function that is
/// to be invoked in the resulting script output.
/// </summary>
/// <value>The callback function name.</value>
public string Callback { get; set; }
/// <summary>
/// Enables processing of the result of an action method by a
/// custom type that inherits from <see cref="T:System.Web.Mvc.ActionResult"/>.
/// </summary>
/// <param name="context">The context within which the
/// result is executed.</param>
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
throw new ArgumentNullException("context");
HttpResponseBase response = context.HttpContext.Response;
if (!String.IsNullOrEmpty(ContentType))
response.ContentType = ContentType;
else
response.ContentType = "application/javascript";
if (ContentEncoding != null)
response.ContentEncoding = ContentEncoding;
if (Callback == null || Callback.Length == 0)
Callback = context.HttpContext.Request.QueryString["callback"];
if (Data != null)
{
// The JavaScriptSerializer type was marked as obsolete
// prior to .NET Framework 3.5 SP1
#pragma warning disable 0618
JavaScriptSerializer serializer = new JavaScriptSerializer();
string ser = serializer.Serialize(Data);
response.Write(Callback + "(" + ser + ");");
#pragma warning restore 0618
}
}
}
Note: Following up on the comments to the OP by #Ranju and others, I figured it was worth posting the "bare minimum" functional code from Ranju's blog post as a community wiki. Though it's safe to say that Ranju added the above and other code on his blog to be used freely, I'm not going to copy his words here.
For ASP.NET Core ,NOT ASP.NET MVC
This is a tailored version for ASP.NET CORE of the solution which exists in the answer
public class JsonpResult : JsonResult
{
public JsonpResult(object value) : base(value)
{
}
public override async Task ExecuteResultAsync(ActionContext context)
{
if (context == null)
throw new ArgumentNullException(nameof(context));
HttpResponse response = context.HttpContext.Response;
if (!String.IsNullOrEmpty(ContentType))
response.ContentType = ContentType;
else
response.ContentType = "application/javascript";
if (Value != null)
{
HttpRequest request = context.HttpContext.Request;
string serializedJson = JsonConvert.SerializeObject(Value);
string result = $"{request.Query["callback"]}({serializedJson})";
await response.WriteAsync(result);
}
}
}
The referenced articles by stimms and ranju v were both very useful and made the situation clear.
However, I was left scratching my head about using extensions, sub-classing in context of the MVC code I had found online.
There was two key points that caught me out:
The code I had derived from ActionResult, but in ExecuteResult there was some code to return either XML or JSON.
I had then created a Generics based ActionResult, to ensure the same ExecuteResults was used independant of the type of data I returned.
So, combining the two - I did not need further extensions or sub-classing to add the mechanism to return JSONP, simply change my existing ExecuteResults.
What had confused me is that really I was looking for a way to derive or extend JsonResult, without re-coding the ExecuteResult. As JSONP is effectively a JSON string with prefix & suffix it seemed a waste. However the underling ExecuteResult uses respone.write - so the safest way of changing is to re-code ExecuteResults as handily provided by various postings!
I can post some code if that would be useful, but there is quite a lot of code in this thread already.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Script.Serialization;
namespace Template.Web.Helpers
{
public class JsonpResult : JsonResult
{
public JsonpResult(string callbackName)
{
CallbackName = callbackName;
}
public JsonpResult()
: this("jsoncallback")
{
}
public string CallbackName { get; set; }
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
var request = context.HttpContext.Request;
var response = context.HttpContext.Response;
string jsoncallback = ((context.RouteData.Values[CallbackName] as string) ?? request[CallbackName]) ?? CallbackName;
if (!string.IsNullOrEmpty(jsoncallback))
{
if (string.IsNullOrEmpty(base.ContentType))
{
base.ContentType = "application/x-javascript";
}
response.Write(string.Format("{0}(", jsoncallback));
}
base.ExecuteResult(context);
if (!string.IsNullOrEmpty(jsoncallback))
{
response.Write(")");
}
}
}
public static class ControllerExtensions
{
public static JsonpResult Jsonp(this Controller controller, object data, string callbackName = "callback")
{
return new JsonpResult(callbackName)
{
Data = data,
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
public static T DeserializeObject<T>(this Controller controller, string key) where T : class
{
var value = controller.HttpContext.Request.QueryString.Get(key);
if (string.IsNullOrEmpty(value))
{
return null;
}
JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();
return javaScriptSerializer.Deserialize<T>(value);
}
}
}
//Example of using the Jsonp function::
// 1-
public JsonResult Read()
{
IEnumerable<User> result = context.All();
return this.Jsonp(result);
}
//2-
public JsonResult Update()
{
var models = this.DeserializeObject<IEnumerable<User>>("models");
if (models != null)
{
Update(models); //Update properties & save change in database
}
return this.Jsonp(models);
}
the solution above is a good way of working but it should be extendend with a new type of result instead of having a method that returns a JsonResult you should write methods that return your own result types
public JsonPResult testMethod() {
// use the other guys code to write a method that returns something
}
public class JsonPResult : JsonResult
{
public FileUploadJsonResult(JsonResult data) {
this.Data = data;
}
public override void ExecuteResult(ControllerContext context)
{
this.ContentType = "text/html";
context.HttpContext.Response.Write("<textarea>");
base.ExecuteResult(context);
context.HttpContext.Response.Write("</textarea>");
}
}