JasperFx / alba

Easy integration testing for ASP.NET Core applications
https://jasperfx.github.io/alba
Apache License 2.0
407 stars 39 forks source link

Allow query string parameters to be appended to request #39

Closed jrios closed 7 years ago

jrios commented 7 years ago

I've been attempting to write tests against controller methods with query string parameters. I can safely hit those endpoints through something like Postman when the app is started, but I cannot hit them in any way that I could find using Alba.

Here's an example of failing tests:

Invoking Input with a string - results in 204

[Fact]
public Task returns_successfully_when_passed_input_as_query_string()
{
    return run(_ =>
    {
        _.Get.Input("value");
        _.Get.Url("/query-string");
    });
}

Invoking Input with an object - results in 204

[Fact]
public Task returns_successfully_when_passed_input_as_query_string()
{
    return run(_ =>
    {
        _.Get.Input(new { test = "value" });
        _.Get.Url("/query-string");
    });
}

Invoking Url with the query string parameter appended - results in 404:

[Fact]
public Task returns_successfully_when_passed_input_as_query_string()
{
    return run(_ =>
    {
        _.Get.Url("/query-string?test=value");
    });
}

This PR is an attempt to try and add the capability to append query string parameters to the request.

Here's an example of the usage that I've come up with.

[Fact]
public Task can_send_querystring_parameters()
{
    return run(_ =>
    {
        _.Get.QueryString("test", "value");
        _.Get.Url("/query-string");
    });
}

However, I'm not sure why the code I've written doesn't work. It isn't setting any values in the QueryString collection at all and I don't know why.

Is this a use case worth solving for? it's possible to write tests that invoke the controller method directly.

jrios commented 7 years ago

I've added all of the tests I noted above to specs_against_aspnet_core_app.cs in a separate commit that I can get rid of later.

joemcbride commented 7 years ago

👍 Could add an overload that takes a class, like the FormData method.

public SendExpression QueryString<T>(T target)
{
    typeof(T).GetProperties().Where(x => x.CanWrite && x.CanRead).Each(prop =>
    {
        var rawValue = prop.GetValue(target, null);

        Context.Request.QueryString.Add(prop.Name, rawValue?.ToString() ?? string.Empty);
    });

    // fields too?

    return new SendExpression(Context);
}

_.Get.QueryString(new { test = "value" }).ToUrl("/query-string");

// kind of liking `With`
_.Get.WithQueryString(new { test = "value" }).ToUrl("/query-string");
jrios commented 7 years ago

Interesting thought, it would be worth adding just to account for endpoint methods with more args. I can add that once I figure out why the initial method I've added doesn't seem to work.

jeremydmiller commented 7 years ago

Pulled in w/ a rebase