Надеюсь, что все в целости и сохранности во время экстренного события covid-19 ...
Я создаю среду автоматизации тестирования, используя C# in. Net Core. Мы также используем SpecFlow для реализации BDD. Я работаю над поддержкой REST API и пытаюсь отделить REST DTO, который используется для управления ответом от фреймворка - я использую Generics для этого. Я работал с шаблонами в Java и предоставил некоторый код о том, как мы реализовали это в Java с помощью Spring ... Попытка переместить этот дизайн в C# ...
Извините, это так долго - может быть, некоторая помощь для других людей.
Спасибо за любую помощь.
Вот реализация Java (рабочая) - будет предпринята попытка C# ...
// Test Implementation
// The details of the test (DTO) are decoupled from the test automation
// framework using the Templated of the RESTResponse Class
// Feature File (Test)
@service
Feature: Case Category Service
Background:
Scenario Outline: Verify retrieving case category
When I call the get case category service
| Case Category ID |
| <Case Category ID> |
Then I will get the case category service response:
| Case Category ID | Case Category Name | Case Category Comment |
| <Case Category ID> | <Case Category Name> | <Case Category Comment> |
Examples:
| Case Category ID | Case Category Name | Case Category Comment |
| 1000000 | Appeal | These are appeal cases |
Java Реализация (рабочая)
Файл шага Реализация (тест)
Обратите внимание, как CountyResponseDTO в ответе использует шаблон RESTResponse
@When("^I call the get county service:$")
public void getCounty(DataTable table) throws Throwable
{
RESTResponse<CountyResponseDTO> response = countyService.getCounty(new BaseDataTable(table));
globals.put("countyResponse", response.getObject());
}
@Then("^I will get the county service response:$")
public void validateCountyServiceResponse(DataTable table) throws Throwable
{
BaseDataTable t = new BaseDataTable(table);
CountyResponseDTO responseDTO = globals.get("countyResponse");
softAssert.assertEquals("ID from cucumber table matches DTO response ID",
t.getValue("County ID"),
responseDTO.getCountyID());
softAssert.process();
}
Java Реализация (рабочая)
Реализация сервиса (тест)
@QAComponent("caseCategoryService")
public class CaseCategoryService extends AbstractRESTService
{
// Returns a case catgory.
public RESTResponse<CaseCategoryResponseDTO> getCaseCategory(BaseDataTable table)
{
return get(CaseCategoryResponseDTO.class, "caseCategoryService.getCaseCategory.v1",
table.getValue("Case Category ID"));
}
}
Java Реализация (рабочая)
Test Automation Framework
Отсоединяется от вышеуказанного теста с использованием шаблонного RESTResponse
Реализация RestClient (Framework)
// Issues an HTTP get request, for returning a resource from the system.
protected <T> RESTResponse<T> get(Class<T> responseClass, String pathKey, String... pathValues)
{
return get(null, responseClass, pathKey, pathValues);
}
Java Реализация (рабочая)
Реализация RestClient (Framework)
// Issues an HTTP get request, for returning a resource from the system
protected <T> RESTResponse<T> get(Map<String, String> params, Class<T> responseClass, String pathKey, String... pathValues)
{
RESTResponse response = null;
StringBuilder builder = new StringBuilder(getURL(pathKey, pathValues));
if (params != null && params.size() > 0)
{
builder.append("?");
for (Map.Entry<String, String> entry : params.entrySet())
{
builder.append(entry.getKey() + "=" + entry.getValue());
}
}
try
{
log.debug("Sending GET request: " + builder.toString());
ResponseEntity<T> r = template.exchange(builder.toString(), HttpMethod.GET,
new HttpEntity<Object>(
getHeader()), responseClass);
response = new RESTResponse(r.getBody(), r.getStatusCode().value(), r.getHeaders());
}
catch (HttpClientErrorException exc)
{
response = new RESTResponse(null, exc.getStatusCode().value(), exc.getResponseHeaders());
String errorMessage = exc.getResponseBodyAsString();
response.setErrorMessage(errorMessage);
log.debug("Response error message: " + errorMessage);
}
log.debug("Response code: " + response.getHttpStatusCode());
return response;
}
Java Реализация (рабочая)
Реализация RestClient, RESTResponse (Framework)
public class RESTResponse<T>
{
private T object;
private int httpStatusCode;
private String errorMessage;
private HttpHeaders headers;
// Initializing constructor.
public RESTResponse(T object, int httpStatusCode, HttpHeaders headers)
{
this.object = object;
this.httpStatusCode = httpStatusCode;
this.headers = headers;
}
// Returns the object associated with this response. Returns null if no object was received.
public T getObject()
{
return object;
}
// Returns the HTTP status code associated with this response.
public int getHttpStatusCode()
{
return httpStatusCode;
}
// Convenience wrapper for quickly getting the ID header.
public String getIDHeader()
{
return getHeader("id");
}
// Returns the HTTP header value for the specified header name.
public String getHeader(String headerName)
{
return headers.get(headerName).get(0);
}
// Returns the error message associated with this response.
// Returns null if no error message is available.
public String getErrorMessage()
{
return errorMessage;
}
// Sets the error message associated with this response.
public void setErrorMessage(String errorMessage)
{
this.errorMessage = errorMessage;
}
}
C# Реализация (справка)
C# Реализация (справка)
Опять же - мы пытаемся реализовать подобный дизайн в C#. Я отмечу в реализации REST Get (), где у меня есть некоторые проблемы с использованием Generics в десериализации ответа.
Здесь много кода - извините, я добавил комментарий HELP ниже - где я думаю, что мне нужно HELP
// Feature File (SpecFlow BDD)
@service
Feature: RestClient Test
In order to test the RestClient implementation using the Automation Framework
As a Software Engineer testing the Automation Framework
I want to see that the RestClient works with the standard Http Methods the Framework
@mytag
Scenario: Implment and test the Http Get Method
Given I have access to the host system
When I provide the record id to the Get Method URL as 10
Then the Get Method will return the response as expected as 200
C# Реализация (Справка)
Реализация определения шага (SpecFlow)
[Then(@"the Get Method will return the response as expected as (.*)")]
public void ThenTheGetMethodWillReturnTheResponseAsExpectedAs(int expectedHttp)
{
logger.Debug("Inside: RestClientTestSteps::ThenTheGetMethodWillReturnTheResponseAsExpectedAs()");
logger.Debug("expectedHttp: {0} ", expectedHttp);
// ****************
// ***** HELP *****
// ****************
// Don't know how to use generics to get the response in the
// form of the RepositoryDto retuendd from the Get() from the framework
// This will not work
RepositoryDto responseDTO<RepositoryDto> = baseRestClient.Get("https://api.github.com/orgs/dotnet/repos",
typeof(RepositoryDto));
// Now we will test
softAssert.assertEquals("HTTP Result from SpecFlow matches DTO response ID",
expectedHttp,
responseDTO.getHttpStatusCode());
softAssert.process();
}
C# Реализация (справка)
Framework REST Get Реализация
Использование универсальных шаблонов и шаблонов
public Object Get(string url, Type responseClass)
{
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/vnd.github.v3+json"));
client.DefaultRequestHeaders.Add("User-Agent", ".NET Foundation Repository Reporter");
// ****************
// ***** HELP *****
// ****************
// Again, attempting to decouple this Get() method from the Response DTO that is
// specific to the test. We are passing in the DTO Object and then using
// Activator.CreateInstance() to create the object.
// Then I need to serialize the response from the GetStringAsync() call into
// the Response DTO object ???
Object theObject = Activator.CreateInstance(responseClass).;
var response = client.GetStringAsync(new Uri(url)).Result;
repositories = JsonSerializer.Deserialize<List<responseClass>> (response);
return repositories;
}
C# Реализация
Класс ответа REST с использованием Generics
public class BaseRestResponse<T>
{
private T Object;
private int httpStatusCode;
private string errorMessage;
private HttpHeaders headers;
public BaseRestResponse(T input, int httpStatusCode, HttpHeaders headers)
{
this.Object = input;
this.httpStatusCode = httpStatusCode;
this.headers = headers;
}
public T getObject()
{
return Object;
}
public int getHttpStatusCode()
{
return httpStatusCode;
}
public string getIDHeader()
{
return getHeader("id");
}
public string getHeader(string headerName)
{
return headers.GetValues(headerName).ToString();
}
public string getErrorMessage()
{
return errorMessage;
}
public void setErrorMessage(String errorMessage)
{
this.errorMessage = errorMessage;
}
}
Еще раз спасибо за любые предложения
Оставайтесь в безопасности ...
Спасибо, Крис