-
Notifications
You must be signed in to change notification settings - Fork 19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
엔드포인트 리팩토링 #63
Comments
의정팀이 담당하겠습니다! |
우선 엔드포인트 하나만 해 보세요: https://github.com/devrel-kr/nhn-toast-notification-service-custom-connector/blob/main/src/nt-sms/Triggers/GetMessage.cs 대강의 슈도 코드는 대충 이런 느낌? try
{
var payload = this._workflow
.ValidateHeader(req)
.ValidateQuery(req)
.BuildRequestUrl<GetMessageRequestPaths>(this._settings)
.Invoke();
return new OkObjectResult(payload);
}
catch (Exception ex)
{
return new BadRequestResult();
} |
해당 이슈를 해결함에 있어 제가 이해한 것이 맞는지 멘토님께 확인하고 싶습니다. |
맞습니다. 제가 위에 적어놓은 수도 코드를 보면 |
멘토님, 리팩토링에 어려움을 겪고 있어서 도움을 요청해보려 합니다..
서비스 레이어에 이런 식으로 코드를 작성을 하면 멘토님께서 알려주신 Getmessage.cs의 수도코드에서 사용할 수 있지 않을까.. 해서 한 번 시도라도 해보려고 작성을 해보았습니다. 여기서 제가 궁금한 부분은 3가지가 있습니다. 1.리팩토링이 해당 방식과는 전혀 다른지.. 인터페이스(?)로 접근을 해야하는지 궁금합니다. |
I have a question..
|
리팩토링은 현재
테스트 메소드를 만들어 보면 되겠죠? 이따 오피스 아워에서 잠깐 해 볼까요?
오피스 아워에서 한 번 다뤄 보시지욥. |
I would strongly recommend using the interface - the strategy pattern.
That's correct. |
테스트 중 오류가 생긴 부분에 대해 질문이 있습니다. error 문구로 'test.settings.json' 구성 파일을 찾을 수 없다고 나옵니다. 실제 경로가 나와있어서 직접 보면 그 경로에 해당 파일이 없습니다. 원인이 무엇인지 알 수 있을까요? 제가 따로 건드린 코드는 없습니다. |
지금 폴더에 보면 그리고, 이 클라스 위에 보면 [TestCategory("Integration")] 이라고 보일텐데, 이 테스트는 실제 API를 호출하는 경우라서 이건 별도의 방법을 통해 테스트 해야 합니다. 따라서, 테스트를 돌리실 때 아래 명령어를 사용하세요. dotnet test . --filter:"TestCategory!=Integration" |
멘토님께서 보여주신 validateheader부분을 리팩토링하는 과정을 복습하고, ValidateQuery리팩토링을 진행하다가 궁금한 점이 생겼습니다. public class HttpTriggerWorkflow : IHttpTriggerWorkflow
{
private RequestHeaderModel _headers;
/// <inheritdoc />
public async Task<IHttpTriggerWorkflow> ValidateHeaderAsync(HttpRequest req)
{
var headers = req.To<RequestHeaderModel>(useBasicAuthHeader: true)
.Validate();
this._headers = headers;
return await Task.FromResult(this).ConfigureAwait(false);
}
} 해당 부분은 서비스 레이어를 구성하고 있는 HttpTriggerWorkflow.cs파일 중 일부입니다. 여기서 제가 이해한 바로는 리팩토링할 ValidateHeader, ValidateQuery, requestURL 로직들을 각각의 Task로 나누어서 해야할 것 같다는 생각이 들었습니다. 해당 방식이 맞을까요? public class HttpTriggerWorkflow : IHttpTriggerWorkflow
{
private RequestHeaderModel _headers;
private GetMessageRequestQueries _queries;
/// <inheritdoc />
public async Task<IHttpTriggerWorkflow> ValidateHeaderAsync(HttpRequest req)
{
var headers = req.To<RequestHeaderModel>(useBasicAuthHeader: true)
.Validate();
this._headers = headers;
return await Task.FromResult(this).ConfigureAwait(false);
}
/// <inheritdoc />
public async Task<IHttpTriggerWorkflow> ValidateGetMessageRequestQueryAsync(HttpRequest req)
{
var queries = await req.To<GetMessageRequestQueries>(SourceFrom.Query).Validate(this._validator)
.ConfigureAwait(false);
this._queries = queries;
return await Task.FromResult(this).ConfigureAwait(false);
}
} 이런식으로 Task를 추가하는 것이 맞을까요? 또한, 모든 api들에 있어서 동일한 Header와는 다르게 GetMessage, ListMessage 등... 각 api마다 query부분이 GetMessageRequestQueries, ListMessagesRequestQueries 이런식으로 다른데, 각각의 다른 query도 Task로 따로 따로 나누어야 하나요? |
TestMethod를 생성하는 기준이 궁금합니다. public static RequestHeaderModel Validate(this RequestHeaderModel headers)
{
if (string.IsNullOrWhiteSpace(headers.AppKey))
{
throw new RequestHeaderNotValidException("Not Found") { StatusCode = HttpStatusCode.NotFound };
}
if (string.IsNullOrWhiteSpace(headers.SecretKey))
{
throw new RequestHeaderNotValidException("Unauthorized") { StatusCode = HttpStatusCode.Unauthorized };
}
return headers;
} 제가 이해한 바로는 멘토님께서 ValidateHeader에 대한 TestMethod를 작성하실 때 RequestHeaderValidator.cs파일의 해당 코드를 참고하여 AppKey와 SecretKey를 확인하여 RequestHeaderNotValidException를 throw하는 것을 보고 작성하신 것으로 생각했습니다. public static class GetMessageRequestQueryValidatorExtension
{
/// <summary>
/// Validates the request query parameters against GetMessage.
/// </summary>
/// <param name="headers"><see cref="GetMessageRequestQueries"/> instance.</param>
/// <returns>Returns the <see cref="GetMessageRequestQueries"/> instance.</returns>
public static async Task<GetMessageRequestQueries> Validate(this Task<GetMessageRequestQueries> queries, IValidator<GetMessageRequestQueries> validator)
{
var instance = await queries.ConfigureAwait(false);
var result = validator.Validate(instance);
if (result.IsValid)
{
return instance;
}
throw new RequestQueryNotValidException("Invalid Query Parameters") { StatusCode = HttpStatusCode.BadRequest };
}
}
/// <summary>
/// this represents the validator entity for the GetMessage request query parameters.
/// </summary>
public class GetMessageRequestQueryValidator : AbstractValidator<GetMessageRequestQueries>
{
/// <summary>
/// Initializes a new instance of the <see cref="GetMessageRequestQueryValidator"/> class.
/// </summary>
public GetMessageRequestQueryValidator()
{
this.RuleFor(p => p.RecipientSequenceNumber).GreaterThan(0);
}
} 그렇다면 동일한 흐름으로 GetMessageRequestQueryValidator.cs파일에 존재하는 해당 코드를 보고 TestMethod를 작성해야겠다고 생각을 했습니다. 하지만, 해당 코드를 보고 TestMethod를 어떤식으로 몇 가지를 작성해야 할지 감이 잡히질 않습니다. |
맞습니다.
쿼리 유효성 검사는 각 엔드포인트마다 다르기 때문에 이를 추상화 시키려면 제너릭을 추가하셔야 합니다. 예를 들자면... public interface IHttpTriggerWorkflow
{
Task<IHttpTriggerWorkflow> ValidateQueryAsync<T>(HttpRequest req);
} 이런 식으로 인터페이스를 구상하시면 좋겠죠? |
|
해당 이슈는 이에 Validators 폴더에 멘토님이 알려주신 RequestQueryValidators.cs 클래스를 추가하니 (using Toast.Sms.Validators는 삭제 가능) using System.Threading.Tasks;
using FluentValidation;
using Toast.Common.Models;
namespace Toast.Common.Validators
{
public static class RequestQueryValidator
{
public static async Task<T> Validate<T>(this Task<T> queries, IValidator<T> validator) where T : BaseRequestQueries
{
return await queries.Validate(validator).ConfigureAwait(false);
}
}
} 해결되었습니다! |
//쿼리 유효성 검사 통과X
[TestMethod]
public void Given_ValidQueries_fails_When_Invoke_ValidateQueriesAsync_Then_It_Should_Throw_Exception()
{
var queries = new QueryString();
queries.Add("Name","Value");
//var queries = new BaseRequestQueries();
var req = new Mock<HttpRequest>();
req.SetupGet(p => p.QueryString).Returns(queries);
//var validator = new RequestQueryValidator();
var validator = new Mock<IValidator<BaseRequestQueries>>();
var workflow = new HttpTriggerWorkflow();
Func<Task> func = async () => await workflow.ValidateQueriesAsync<BaseRequestQueries>(req.Object, validator);
func.Should().ThrowAsync<RequestQueryNotValidException>();
}
//쿼리 유효성 검사 통과o
[DataTestMethod]
[DataRow("hello", "world")]
public async Task Given_ValidQueries_When_Invoke_ValidateQueriesAsync_Then_It_Should_Return_Result(string name, string value)
{
var queries = new QueryString();
queries.Add("Name","Value");
var req = new Mock<HttpRequest>();
req.SetupGet(p => p.QueryString).Returns(queries);
var validator = new Mock<IValidator<BaseRequestQueries>>();
var workflow = new HttpTriggerWorkflow();
var result = await workflow.ValidateQueriesAsync<BaseRequestQueries>(req.Object, validator);
result.Should().BeOfType<HttpTriggerWorkflow>();
} |
Requirement:
The text was updated successfully, but these errors were encountered: