2017-02-21 43 views
1

Я немного почесываю голову, пытаясь выяснить, как проверить что-то вроде следующего: Вот метод GetProjects.Как пропустить UserId в NUnit?

[Authorize] 
[HttpGet] 
[Route("api/UserProject/GetUserProjects")] 
public HttpResponseMessage GetProjects() 
{ 
    string userId = User.Identity.GetUserId(); 
    if (!ModelState.IsValid) 
    { 
     return new HttpResponseMessage(HttpStatusCode.BadRequest); 
    } 

    try 
    { 
     List<ProjectDto> userProjectsDtos = projectBll.GetProjects(userId); 
     return Request.CreateResponse(HttpStatusCode.OK, userProjectsDtos); 
    } 
    catch (Exception) 
    { 
     return new HttpResponseMessage(HttpStatusCode.InternalServerError); 
    } 
} 

И вот я пытаюсь запустить тест NUnit для этого метода.

[TestClass] 
public class TestUserProjects 
{ 
    [TestMethod] 
    public void GetUserProjectsTest() 
    { 
     // Arragnge 
     var controller = new UserProjectController(); 
     controller.Request = new HttpRequestMessage(); 
     controller.Configuration = new HttpConfiguration(); 

     foreach (var testUserId in GetTestUserIds()) 
     { 
      // Act 
      var response = controller.GetProjects(); 

      // Assert 
      List<ProjectDto> projects; 
      Assert.IsTrue(response.TryGetContentValue<List<ProjectDto>>(out projects)); 
      //Assert.AreEqual(5, projects.Count); // Check projects count 
      Assert.AreEqual(HttpStatusCode.OK,response.StatusCode); 
      Assert.AreEqual(HttpStatusCode.OK, response.StatusCode,"GetUserProjects : id is {0} and count is {1}",testUserId,projects.Count); 
      System.Diagnostics.Debug.WriteLine("GetUserProjects : for id {0} ProjectCount = {1}", testUserId, projects.Count); 
     } 
    } 
} 

Я пытаюсь передать USERID, но не знаю, куда писать это.

ответ

1

Если запрос должен быть аутентифицирован, то свойство User должно быть заполнено по принципу аутентифицированного пользователя. Однако во время единичного теста это не заполняется каркасом.

Для ApiController вы можете установить свойство User во время проведения модульного испытания. Этот метод GetUserId() расширения однако ищет ClaimsIdentity так что вы должны предоставить один

[TestClass] 
public class TestUserProjects { 
    [TestMethod] 
    public void GetUserProjectsTest() { 
     // Arrange 
     var controller = new UserProjectController(); 
     controller.Request = new HttpRequestMessage(); 
     controller.Configuration = new HttpConfiguration(); 

     foreach (var testUserId in GetTestUserIds()) { 
      //Arrange specific user 
      var identity = new GenericIdentity(testUserId, ""); 
      identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, testUserId.ToString())); 
      identity.AddClaim(new Claim(ClaimTypes.Name, testUserId.ToString())); 

      var principal = new GenericPrincipal(identity, roles: new string[] { }); 
      var user = new ClaimsPrincipal(principal); 

      controller.User = user; 

      // Act 
      var response = controller.GetProjects(); 

      // Assert 
      List<ProjectDto> projects; 
      Assert.IsTrue(response.TryGetContentValue<List<ProjectDto>>(out projects)); 
      //Assert.AreEqual(5, projects.Count); // Check projects count 
      Assert.AreEqual(HttpStatusCode.OK,response.StatusCode); 
      Assert.AreEqual(HttpStatusCode.OK, response.StatusCode,"GetUserProjects : id is {0} and count is {1}",testUserId,projects.Count); 
      System.Diagnostics.Debug.WriteLine("GetUserProjects : for id {0} ProjectCount = {1}", testUserId, projects.Count); 
     } 
    } 
} 
+1

Это решило мою проблему. Теперь мне не нужно менять код, который уже написан. –

1

Его не «макет», вы должны создать другую функцию, которая получит имя пользователя в качестве параметра.

Ваш WebAPI вызовет функцию, и ваш тест проверит логику.

+0

Для этого мне придется изменить существующий код apicontroller? Или есть другой способ? –

+0

Вам нужно будет изменить существующий код apicontroller, извлекая из него логику. –

1

Статический доступ создает жесткие зависимости, которые нельзя легко игнорировать во время тестирования.

Решение заключается в том, чтобы вытащить эту зависимость из тестируемого метода. Я бы сделал что-то вроде так, что зависимость IUserProvider может быть издеваема при тестировании и предоставить любой идентификатор пользователя, подходящий для теста.

public interface IUserProvider 
{ 
    public string GetUserId(); 
} 

public class UserProvider : IUserProvider 
{ 
    public string GetUserId() 
    { 
     return User.Identity.GetUserId(); 
    } 
} 

public class UserProjectController 
{ 
    private IUserProvider UserProvider { get; set;} 

    public UserProjectController(IUserProvider userProvider) 
    { 
     UserProvider = userProvider; 
    } 

    [Authorize] 
    [HttpGet] 
    [Route("api/UserProject/GetUserProjects")] 
    public HttpResponseMessage GetProjects() 
    { 
     string userId = UserProvider.GetUserId(); 
     if (!ModelState.IsValid) 
     { 
      return new HttpResponseMessage(HttpStatusCode.BadRequest); 
     } 

     try 
     { 
      List<ProjectDto> userProjectsDtos = projectBll.GetProjects(userId); 
      return Request.CreateResponse(HttpStatusCode.OK, userProjectsDtos); 
     } 
     catch (Exception) 
     { 
      return new HttpResponseMessage(HttpStatusCode.InternalServerError); 
     } 
    } 
} 

Синтаксис для издевательства IUserProvider при тестировании будет меняться с использованием различных тестовых фреймворков. Использование Moq это выглядит следующим образом

[TestClass] 
public class TestUserProjects 
{ 
    [TestMethod] 
    public void GetUserProjectsTest() 
    { 
     // Arrange 
     var userProviderMock = new Mock<IUserProvider>(); 
     userProviderMock.Setup(userProvider => userProvider.GetUserId()) 
         .Returns("4e934c03-b02f-47bf-8bdf-e1c98a737cc6"); 
     var controller = new UserProjectController(userProviderMock.Object); 
     controller.Request = new HttpRequestMessage(); 
     controller.Configuration = new HttpConfiguration(); 

     foreach (var testUserId in GetTestUserIds()) 
     { 
      // Act 
      var response = controller.GetProjects(); 

      // Assert 
      List<ProjectDto> projects; 
      Assert.IsTrue(response.TryGetContentValue<List<ProjectDto>>(out projects)); 
      //Assert.AreEqual(5, projects.Count); // Check projects count 
      Assert.AreEqual(HttpStatusCode.OK,response.StatusCode); 
      Assert.AreEqual(HttpStatusCode.OK, response.StatusCode,"GetUserProjects : id is {0} and count is {1}",testUserId,projects.Count); 
      System.Diagnostics.Debug.WriteLine("GetUserProjects : for id {0} ProjectCount = {1}", testUserId, projects.Count); 
     } 
    } 
} 

Первые строки в аранжировать раздел нового создать макет из IUserProvider и установок GetUserId() вернуть тестовый идентификатор пользователя.

+0

Это хороший способ. Одно еще неясно. Как я могу вызвать метод getUserId и использовать этот userId, чтобы получить UserProjects в NUnit? Потому что я хочу протестировать GetProjects() для разных пользователей. –