jb.
jb.

Reputation: 1918

Testing routes in a .NET Core Web application

I'm trying to write a suite of tests that will confirm that the expected routes are going to the right Controllers/Actions.

I have part of it done by looking at examples elsewhere, but now I don't know how (or if it is possible) to get the controller details from the objects I have available.

[Test]
public void Test_A_Route()
{
    var server = new TestServer(
                new WebHostBuilder()
                .UseEnvironment("Development")
                .UseConfiguration(GetConfiguration())
                .UseStartup<Startup>());
    var client = server.CreateClient();

    var response = client.GetAsync("/My/Url/").GetAwaiter().GetResult();
    response.EnsureSuccessStatusCode();

    string contentResult = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
    contentResult.Should().Contain("Some text from my webpage that is hopefully unique");
}

I want to be able to verify the following things:

Any idea how to go about it?

Upvotes: 1

Views: 1796

Answers (2)

Adam Małek
Adam Małek

Reputation: 311

I think You could use this IActionFilter for this task:

public class DebugFilter : IActionFilter
{
    bool enabled = false;
    IDictionary<string, object> arguments = null;

    public void OnActionExecuting(ActionExecutingContext context)
    {
        enabled = context.HttpContext.Request.Headers.ContainsKey("X-Debug");
        if (enabled)
        {
            arguments = context.ActionArguments;
        }
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        if (enabled)
        {
            var controllerName = context.Controller.GetType().Name;
            var actionName = context.ActionDescriptor.DisplayName;

            context.HttpContext.Response.Headers.Add("X-Controller-Name", controllerName);
            context.HttpContext.Response.Headers.Add("X-Action-Name", actionName);
            context.HttpContext.Response.Headers.Add("X-Action-Model", JsonConvert.SerializeObject(arguments));
        }
    }
}

and register it globally in Your Startup.cs file:

        #if DEBUG
        services.AddMvc(options =>
        {
            options.Filters.Add(new DebugFilter());
        })
        #else
        services.AddMvc()
        #endif
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

After that You only include 'X-Debug' header in Your test and receive all informations You want from response headers.

Postman screen of response

EDIT: this is ofc very simple class, You have access to ViewData, Result, TempData and many more

Upvotes: 2

Hasan
Hasan

Reputation: 1298

To get controller details, I would suggest you to use Flurl. As you can see in the project docs here and below you can assert controller details as follows. As I understand this library fakes HttpClient and in a manner of unit tests you can get your controller method details. I find this project very viable and hope this helps you as well.

    // fake & record all http calls in the test subject
    using (var httpTest = new HttpTest()) {
    // arrange
    httpTest.RespondWith(200, "OK");
    // act
    await yourController.CreatePersonAsync();
    // assert
    httpTest.ShouldHaveCalled("https://api.com/*")
        .WithVerb(HttpMethod.Post)
        .WithContentType("application/json");
}

Upvotes: 1

Related Questions