У меня есть API с несколькими методами. Мне нужно аутентифицировать пользователя с помощью Windows Authentication
, прежде чем он попадет в любой из методов контроллера. Для этого я написал частный метод, чтобы получить UserIdentity
и присвоить его частной bool
переменной.
Каждый из методов контроллера сначала проверяет логическое значение, чтобы подтвердить пользователя, и, если это не удается, возвращает 401
обратно во внешний интерфейс.
Во время написания модульного теста для методов контроллера я не уверен, как смоделировать UserIdentity
или мне следует обновить контроллер таким образом, чтобы разрешить тестирование UserIdentity
Контроллер:
public class DefaultController : ApiController
{
private bool isUsrAuthenticated;
public DefaultController()
{
AuthenticateUser();
}
private void AuthenticateUser()
{
isUsrAuthenticated = User.Identity.IsAuthenticated;
}
[HttpGet]
public IHttpActionResult GetProducts()
{
if (isUsrAuthenticated) { // do something }
else { // throw 401 }
}
[HttpPost]
public IHttpActionResult Update()
{
if (isUsrAuthenticated) { // do something }
else { // throw 401 }
}
}
Результаты модульного теста всегда возвращают 401.
Во время выполнения свойство ApiController.User
устанавливается после вызова конструктора контроллера. Это означало бы, что ваш текущий поток вызова его в конструкторе, например
public DefaultController() {
AuthenticateUser();
}
имеет недостатки и не обеспечивает ожидаемого поведения.
Давайте сначала исправим код, а затем посмотрим на модульный тест.
Вместо этого используйте свойство, например
private bool IsUserAuthenticated {
get {
return User.Identity.IsAuthenticated;
}
}
и соответствующим образом рефакторить код
public class DefaultController : ApiController {
private bool IsUserAuthenticated {
get {
return User.Identity.IsAuthenticated;
}
}
[HttpGet]
public IHttpActionResult GetProducts() {
if (IsUserAuthenticated) { // do something }
else { // throw 401 }
}
[HttpPost]
public IHttpActionResult Update() {
if (IsUserAuthenticated) { // do something }
else { // throw 401 }
}
//...
}
Теперь для тестирования ApiController
свойство User
можно установить при организации модульного теста, чтобы тест выполнялся должным образом.
Например
[TestMethod()]
public void DefaultController_Should_GetProducts() {
//Arrange
var username = "name_here";
var userId = 2;
var identity = new GenericIdentity(username, "");
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, userId.ToString()));
identity.AddClaim(new Claim(ClaimTypes.Name, username));
var principal = new GenericPrincipal(identity, roles: new string[] { });
var user = new ClaimsPrincipal(principal);
var controller = new DefaultController() {
User = user //<-- Set the User on the controller directly
};
//Act
var actionResult = controller.GetProducts();
//Assert
//...
}