I have a put method that accepts inputstream. I want to call this method using rest assured in JUnit.
This is what I used:
with().body(inpustream).put("/service/1"); // i got error 404 forbidden.
POST will return status code 201 and PUT will return 200, and POST will create a new resource but, PUT will update the existing resource. This means we will have to mention which resource we wish to update in the URI itself like below.
import io.restassured.RestAssured;
import static io.restassured.RestAssured.*;
import java.util.HashMap;
import java.util.Map;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import static org.hamcrest.Matchers.*;
public class PUTMethod {
public static Map<String, String> map = new HashMap<String, String>();
#BeforeTest
public void putdata(){
map.put("userId", "2");
map.put("id", "19");
map.put("title", "this is projectdebug.com");
map.put("body", "i am testing REST api with REST-Assured and sending a PUT request.");
RestAssured.baseURI = "http://jsonplaceholder.typicode.com";
RestAssured.basePath = "/posts/";
}
#Test
public void testPUT(){
given()
.contentType("application/json")
.body(map)
.when()
.put("/100")
.then()
.statusCode(200)
.and()
.body("title", equalTo("this is projectdebug.com"));
}
}
Visit http://www.projectdebug.com/send-put-request-using-rest-assured/
for more information.
Actually, you are doing well but sending multipart through PUT is unsecured and is quite random (https://jira.spring.io/browse/SPR-9079). Amend your spring-security.xml to add a filter or use POST method in this case.
You can also try your code by calling another PUT webservice with no stream.
(And what is the error code ? 404 or 403 ?)
A similar problem solved by using MultipartFilter : Spring 3.0 FileUpload only with POST?
Have a look at the following example, where it explains how to use PUT request using Rest Assured:
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import static com.jayway.restassured.RestAssured.*;
import com.jayway.restassured.RestAssured;
import com.jayway.restassured.response.Response;
public class GetStatusCodeTest {
#BeforeClass
public void setBaseUri () {
RestAssured.baseURI = "https://localhost:3000";
}
#Test
public void updateUsingPut () {
Posts post = new Posts();
post.setId ("3");
post.setTitle ("Hello Bhutan");
post.setAuthor ("StaffWriter");
given().body (post)
.when ()
.contentType (ContentType.JSON)
.put ("/posts/3");
}
}
For detailed explanation, you may check out the following link:
https://restservicestesting.blogspot.in/2016/10/automating-put-request-using-rest.html
Related
I'm trying to get a PACT test running on JUnit5. We use JUnit4 for others, but this one will be JUnit5. The error occurs when running the JUnit5 test using the pact annotation on the RequestResponsePact method.
Error : No method annotated with #Pact was found on test class ConsumerContractTest for provider ''.
I've seen Basic Pact/Junit5 Test Setup fails. No method annotated with #Pact was found for provider error, but this is issue was due to the #PactTestFor(pactMethod = "examplePact") not matching the #Pact method name. But on my code it does match.
I can't seem to figure out why I get the error and especially why the error has an empty provider(provider '') despite defining one("some-provider").
Example code :
import au.com.dius.pact.consumer.MockServer
import au.com.dius.pact.consumer.Pact
import au.com.dius.pact.consumer.dsl.PactDslJsonArray
import au.com.dius.pact.consumer.dsl.PactDslWithProvider
import au.com.dius.pact.consumer.junit5.PactConsumerTestExt
import au.com.dius.pact.consumer.junit5.PactTestFor
import au.com.dius.pact.model.RequestResponsePact
import groovyx.net.http.RESTClient
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.springframework.http.HttpStatus
#ExtendWith(PactConsumerTestExt.class)
class ConsumerContractTest {
#Pact(consumer = "some-consumer", provider = "some-provider")
RequestResponsePact examplePact(PactDslWithProvider builder) {
builder
.given("provider state")
.uponReceiving("Contract description")
.method("GET")
.matchPath("/endpoint")
.willRespondWith()
.status(200)
.headers(["Content-Type": "application/vnd.pnf.v1+json"])
.body(new PactDslJsonArray())
.toPact()
}
#Test
#PactTestFor(pactMethod = "examplePact")
void exampleTest(MockServer mockServer) {
def client = new RESTClient(mockServer.getUrl())
}
}
Not sure if that's just the gist you've posted here but I see the return word missing and also the #PactTestFor annotation missing the provider and version. Here is an example I have that works for my project.
import au.com.dius.pact.consumer.dsl.DslPart;
import au.com.dius.pact.consumer.dsl.PactDslJsonBody;
import au.com.dius.pact.consumer.dsl.PactDslWithProvider;
import au.com.dius.pact.consumer.junit5.PactConsumerTestExt;
import au.com.dius.pact.consumer.junit5.PactTestFor;
import au.com.dius.pact.core.model.PactSpecVersion;
import au.com.dius.pact.core.model.RequestResponsePact;
import au.com.dius.pact.core.model.annotations.Pact;
import io.restassured.response.Response;
import io.restassured.specification.RequestSpecification;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import java.util.HashMap;
import java.util.Map;
import static com.example.mbbackend.config.Constants.*;
import static com.example.mbbackend.util.Utils.getRequestSpecification;
import static org.junit.jupiter.api.Assertions.assertEquals;
#ExtendWith(PactConsumerTestExt.class)
class GetActorIT {
Map<String, String> headers = new HashMap<>();
String path = "/api/mb/actor/";
#Pact(provider = PACT_PROVIDER, consumer = PACT_CONSUMER)
public RequestResponsePact createPact(PactDslWithProvider builder) {
headers.put("Content-Type", "application/json");
DslPart bodyReturned = new PactDslJsonBody()
.uuid("id", "1bfff94a-b70e-4b39-bd2a-be1c0f898589")
.stringType("name", "A name")
.stringType("family", "A family")
.stringType("imageUrl", "http://anyimage.com")
.close();
return builder
.given("A request to retrieve an actor")
.uponReceiving("A request to retrieve an actor")
.pathFromProviderState(path + "${actorId}", path + "1bfff94a-b70e-4b39-bd2a-be1c0f898589")
.method("GET")
.headers(headers)
.willRespondWith()
.status(200)
.body(bodyReturned)
.toPact();
}
#Test
#PactTestFor(providerName = PACT_PROVIDER, port = PACT_PORT, pactVersion = PactSpecVersion.V3)
void runTest() {
//Mock url
RequestSpecification rq = getRequestSpecification().baseUri(MOCK_PACT_URL).headers(headers);
Response response = rq.get(path + "1bfff94a-b70e-4b39-bd2a-be1c0f898589");
assertEquals(200, response.getStatusCode());
}
}
Scenario: Verify the manifest of published app
1. Given Base url "baseUrl" and path "basepath"
2. And Headers are
3. And Query parameter
4. And App with below details
5. When I execute the another API with Base url "baseUrl" and path "basePath"
6. And Append with Attributevalue (complete url will be , baseUrl + basePath + AttributeValue )
7. And api headers
8. And query parameters
9. Then Success message with 200 status code
I have implemented something very similar recently. You can utilize below code and modify it to your need. You'll probably need to omit some steps from your feature . Those steps are included as part of step def implementation in below code
Feature
#get
Scenario: get employee
Given an employee exist in the database with id "2"
When user retrieves employee info by id
Then the status code for get employee is 200
StepDefs
import io.cucumber.java.en.Given;
import io.cucumber.java.en.When;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.And;
import io.restassured.RestAssured;
import io.restassured.path.json.JsonPath;
import io.restassured.response.Response;
import io.restassured.response.ValidatableResponse;
import io.restassured.specification.RequestSpecification;
import static org.junit.jupiter.api.Assertions.*;
import static org.assertj.core.api.Assertions.assertThat;
public class secondIT {
public static Response response;
public static ValidatableResponse json;
public static RequestSpecification request;
public static String id;
public static JsonPath jsonPathEvaluator;
#Given("an employee exist in the database with id {string}")
public void an_employee_exists_with_id(String ID){
secondIT.id=ID;
RestAssured.baseURI = "http://dummy.www.com/api/v1";
secondIT.request = RestAssured.given();
}
#When("user retrieves employee info by id")
public void user_retrieves_employee_info_by_id(){
secondIT.response = secondIT.request.pathParam("id", secondIT.id).get("/employee/{id}");
secondIT.jsonPathEvaluator = secondIT.response.jsonPath();
assertNotNull(response);
}
#Then("the status code for get employee is {int}")
public void verify_status(int sc){
System.out.println("status code check.. " );
secondIT.json = secondIT.response.then().statusCode(sc);
System.out.println("status code: " + secondIT.response.getStatusCode());
assertEquals(sc,secondIT.response.getStatusCode());
}
}
I have a couple of spring boot rest controllers, and I want a standard JSON response structure to be sent to the client.
The standard response will be composed of responseTime, apiResponseCode, status, apiName, response ( which will vary based on the api). See below:
{
"responseTime": "2020-04-19T08:36:53.001",
"responseStatus": "SUCCESS",
"apiResponseCode": "SUCCESS",
"apiName": "PROPERTY_STORE_GET_PROPERTIES",
"response": [
{
"propertyName": "app.name",
"propertyValue": "property-store"
}
]
}
To achieve this, I have created below model class:
package com.example.response.model;
import java.io.Serializable;
import java.time.LocalDateTime;
import com.example.constants.ApiResponseCode;
import com.example.constants.Status;
public class ApplicationResponse<T> implements Serializable {
private static final long serialVersionUID = -1715864978199998776L;
LocalDateTime responseTime;
Status responseStatus;
ApiResponseCode apiResponseCode;
String apiName;
T response;
public ApplicationResponse(LocalDateTime responseTime, Status status,
ApiResponseCode apiRespCode, String apiName, T response) {
this.responseTime = responseTime;
this.responseStatus = status;
this.apiResponseCode = apiRespCode;
this.apiName = apiName;
this.response = response;
}
// getters and setters
To create a generic response wrapper, I have created below response util class.
import java.time.LocalDateTime;
import com.example.constants.ApiResponseCode;
import com.example.constants.Status;
import com.example.response.model.ApplicationResponse;
public class ResponseUtil {
public static <T> ApplicationResponse<T> createApplicationResponse(String
apiName, T response) {
return new ApplicationResponse<>(LocalDateTime.now(),
Status.SUCCESS, ApiResponseCode.SUCCESS, apiName,
response);
}
private ResponseUtil() {
}
}
Now the ask is that my response from controller should get serialized in the standard way. Shown below is my controller method.
package com.example.propertystore.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RestController;
import com.example.constants.ApiResponseCode;
import com.example.constants.Status;
import com.example.exception.ApplicationException;
import com.example.exception.ApplicationExceptionHelper;
import com.example.propertystore.constants.PropertyStoreApiName;
import com.example.propertystore.dto.PropertyDTO;
import com.example.propertystore.entity.Property;
import com.example.propertystore.service.PropertyStoreService;
import com.example.response.ResponseUtil;
import com.example.response.model.ApplicationResponse;
#RestController
public class PropertyStoreControllerImpl implements PropertyStoreController {
#Autowired
PropertyStoreService propertyStoreService;
#Autowired
ApplicationExceptionHelper exceptionHelper;
#Override
public ApplicationResponse<List<PropertyDTO>> getProperties() throws ApplicationException {
ApplicationResponse<List<PropertyDTO>> response = null;
try {
response = ResponseUtil.createApplicationResponse(
PropertyStoreApiName.PROPERTY_STORE_GET_PROPERTIES.toString(),
propertyStoreService.getProperties());
} catch (Exception e) {
exceptionHelper.raiseApplicationException( HttpStatus.INTERNAL_SERVER_ERROR, Status.FAILURE,
ApiResponseCode.INTERNAL_SERVER_ERROR,
PropertyStoreApiName.PROPERTY_STORE_GET_PROPERTIES.toString(), null);
}
return response;
}}
With the current implementation what I'll have to do is that in my controllers I will have to transform the response by calling ResponseUtil.createApplicationResponse(). This is going to litter the entire controller methods with the createApplicationResponse() method call.
What I wanted to explore is that if there is any cleaner way of achieving this using servlet filters or AOP?
PS: I tried filter option, but couldn't understand how to proceed around it. Got stuck after retrieving the response.getOutputStream() in doFilter().
Hope someone can help?
Just wrap all your responses into a decorator object.
class ResponseDecorator<T> {
//global.fields (time,code, status.....)
T response;
}
Then wrap this response wrapper into the ResponseEntity
The response.getOutputStream that you used and filters are servlet related classes , and i think you can do that without them.Just make your custom response class and add fields however you want your response. Than in the controller , just return new ResponseEntity(HttpStatus.OK,"your message "):
I don't know if this is the behavior you want.
I am getting the errors for this post request and while verifying the body. I am using Maven with TestNG using restassured framework. While using the #DataProvider, I am seeing the errors like for body when used equalTo and containsOnly are throwing errors. all thoughts are truly appreciated.
POST Request with #DataProvider :
package com.inline.restassured;
import static io.restassured.RestAssured.given;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public class FilePostToVirusTotal {
static String baseURL = "https://www.test.com/tapi/v2/file/report";
#DataProvider(name = "md5hashes")
public String[][] createMD5TestData() {
return new String[][] resource {
{"md51", "928bc8b9661f0a1dc4eb3n2bdca48551"},
{"md52", "928bc8b9661f0a1dc4eb3k2bdca48556"},
{"md53", "928bc8b9661f0a1dc4eb3t2bdca48557"},
{"md54", "928bc8b9661f0a1dclk903a2bdca4855"},
{"md55", "928bc8b9661f0a1dc4eb3a2bdca48559"},
};
}
#Test(dataProvider = "md5hashes")
public void md5JsonTest(String apikey, String resource)
{
given().
param("JSON", resource).
param("JSON", "94567jhyeser").
when().
post(baseURL).
then().
assertThat().
statusCode(200)
.body("resource", equalTo(resource)) //the highlighted 'equalTo' is prompting as undefined.
.body("response_code", containsOnly(1, 0, -1));
}
}
Sample Response :
{
"response_code": 0,
"resource": "928bc8b9661f0a1dc4eb3n2bdca48551",
}
I'm working on an Android application that uses Retrofit to create a restful client. In order to debug networks calls, I would like to display or dump the url that's actually being invoked. Is there a way to do this? I've included some code below which shows how the app currently using retrofit.
Client interface definition:
import retrofit.Callback;
import retrofit.http.Body;
import retrofit.http.GET;
import retrofit.http.Headers;
import retrofit.http.POST;
import retrofit.http.Path;
// etc...
public interface MyApiClient {
#Headers({
"Connection: close"
})
#GET("/{userId}/{itemId}/getCost.do")
public void get(#Path("userId") String userId, #Path("itemId") String userId, Callback<Score> callback);
//....etc
}
Service which uses generated client:
// etc...
import javax.inject.Inject;
import retrofit.Callback;
import retrofit.RetrofitError;
import retrofit.client.Response;
#Inject
MyApiClient myApiClient;
// etc...
myApiClient.getCost(myId, itemId, new Callback<Cost>() {
#Override
public void success(Cost cost, Response response) {
Log.d("Success: %s", String.valueOf(cost.cost));
if (cost.cost != -1) {
processFoundCost(cost);
} else {
processMissingCost(itemId);
}
stopTask();
}
#Override
public void failure(RetrofitError error) {
handleFailure(new CostFailedEvent(), null);
}
});
}
call.request().url(), where call is type of retrofit2.Call.
RetrofitError has a getUrl() method that returns the URL.
Also the Response has a getUrl() method as well within the callback.
That, and you can also specify the log level as per this question:
RestAdapter adapter = (new RestAdapter.Builder()).
//...
setLogLevel(LogLevel.FULL).setLog(new AndroidLog("YOUR_LOG_TAG"))
Although based on the docs, LogLevel.BASIC should do what you need.
BASIC
Log only the request method and URL and the response status code and execution time.
Yes, you can enable debug logging by calling setLogLevel() on your RestAdapter.
I typically set logging to LogLevel.FULL for debug builds like so:
RestAdapter adapter = builder.setEndpoint("example.com")
.setLogLevel(BuildConfig.DEBUG ? RestAdapter.LogLevel.FULL : RestAdapter.LogLevel.NONE)
.build();
This will automatically print out all of the information associated with your HTTP requests, including the URL you are hitting, the headers, and the body of both the request and the response.