Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/dotnet-labs/controllerunittests
Unit testing Controllers with ClaimsPrincipal | User | Identity | Claims
https://github.com/dotnet-labs/controllerunittests
claims controller credentials dotnet dotnet5 dotnetcore identity unit-testing unittest user
Last synced: 1 day ago
JSON representation
Unit testing Controllers with ClaimsPrincipal | User | Identity | Claims
- Host: GitHub
- URL: https://github.com/dotnet-labs/controllerunittests
- Owner: dotnet-labs
- License: mit
- Created: 2021-06-25T03:12:56.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2023-12-08T17:33:34.000Z (about 1 year ago)
- Last Synced: 2024-10-24T02:30:35.982Z (4 months ago)
- Topics: claims, controller, credentials, dotnet, dotnet5, dotnetcore, identity, unit-testing, unittest, user
- Language: C#
- Homepage:
- Size: 197 KB
- Stars: 1
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE.md
Awesome Lists containing this project
README
# Controller Unit Tests
[](https://ko-fi.com/I3I63W4OK)

We do different levels of testings against controllers. When unit testing controller logic, the test only executes a single action method without going through the framework's request/response pipeline. In other words, the filter attributes (e.g., the `Authorize` attribute ), model binding, and middlewares do not affect unit tests for controllers. Thus, unit testing controller logic is quite similar to testing a regular class where we can mock dependencies and stage input values and verify outputs.
One thing is different is that a controller has an implicit dependency, `ControllerContext`, inherited from `ControllerBase`. The `ControllerContext` includes the frequently used `HttpContext`, `ModelState`, and other features.
In this article, we will go over some use cases when unit testing an action method that involves HttpContext. For example, an action method checks the current user's role based on `ClaimIdentity`, an action method checks HttpRequest header values. We will see how to stage HttpContext and Request. Following a similar fashion, we should also know how to stage Response and ModelState in unit tests.
## Claims
Claims are usually being used to inspect permissions and/or differentiate results. For example, in an action method, we can first get a user's role using `User.FindFirstValue(ClaimTypes.Role)`, then determine the next step based on the role's permission level.
When unit testing an action method, we want to check the behaviors for different user roles. In this case, we can configure the controller's ControllerContext and set the HttpContext with a desired user. Let's take a look at the following test.
```csharp
var user = new ClaimsPrincipal(new ClaimsIdentity(new[] {
new Claim(ClaimTypes.NameIdentifier, "11234568"),
new Claim(ClaimTypes.Name, "admin last"),
new Claim(ClaimTypes.Role, "Admin")
}));
var controller = new ValuesController(new NullLogger())
{
ControllerContext = { HttpContext = new DefaultHttpContext { User = user } }
};var response = controller.Get();
Assert.IsInstanceOfType(response, typeof(OkObjectResult));
var result = ((OkObjectResult)response).Value as string[];
Assert.IsNotNull(result);
Assert.AreEqual(2, result.Length);
Assert.AreEqual("value1", result[0]);
Assert.AreEqual("value2", result[1]);
```## Request Headers
Knowing how to hook up HttpContext to a controller, we can try something out about configuring Http Request.
Let's use a contrived action method as an example. The logic in this action method is based on the language in Request Headers, where the language value can be obtained by using `var lang = Request.Headers["lang"].ToString();`. In order to stage a request header key-value pairs, we can first attach an HttpContext to the controller, then set up the desired request header.
```csharp
var controller = new ValuesController(new NullLogger())
{
ControllerContext = new ControllerContext { HttpContext = new DefaultHttpContext() }
};
controller.Request.Headers["lang"] = language;var response = controller.GetValueById(id);
Assert.IsInstanceOfType(response, typeof(OkObjectResult));
```## ModelState
Similarly, we can manipulate ModelState based on our needs.
```csharp
var controller = new ValuesController(new NullLogger());
controller.ModelState.Clear();
controller.ModelState.AddModelError("test", "test");
```## License
Feel free to use the code in this repository as it is under MIT license.
[](https://ko-fi.com/I3I63W4OK)