Модульное тестирование веб-API IHttpActionResponse коды состояния - PullRequest
0 голосов
/ 13 мая 2018

Я работаю над проектом модульного тестирования для тестирования Web API v2 с IHttpActionResponse в качестве типа возврата.

Я не могу найти способ протестировать все коды состояния с возвращением IHttpActionResponseтип.Особенно пост необходимо проверить http статус кода.Здесь я создал несколько тестов для Get и GetById.Дайте мне знать, как мы можем проверить все коды состояния, возвращающие IHttpActionResponse.

Код контроллера API

public class StudentController : ApiController
{
    IRepository<Student> repository;
    ITransformers<StudentModel, Student> transformer;

    public StudentController(IRepository<Student> studentRepository, ITransformers<StudentModel, Student> studentTransformer)
    {
        repository = studentRepository;
        transformer = studentTransformer;
    }

    [HttpGet]
    public IHttpActionResult Get()
    {
        IEnumerable<Student> students = null;

        try
        {
            students = repository.Get();

            if (students.Count<Student>() > 0)
            {
                return Ok(students);
            }
            else
            {
                return StatusCode(HttpStatusCode.NoContent);
                //return Content(HttpStatusCode.NoContent, students);
            }
        }
        catch (Exception ex)
        {
            return InternalServerError(ex);
        }
    }

    [HttpGet]
    public IHttpActionResult Get(int Id)
    {
        Student student = null;

        try
        {
            student = repository.GetById(Id);

            if (student != null)
            {
                return Ok(student);
            }
            else
            {
                return NotFound();
            }
        }
        catch (Exception ex)
        {
            return InternalServerError(ex);
        }
    }

    [HttpPost]
    public IHttpActionResult Post(StudentModel studentModel)
    {
        try
        {
            Student student = transformer.TransformModelToEntity(studentModel);
            int result = repository.Save(student);

            if (result > 0)
            {
                student.Id = result;
                return Content(HttpStatusCode.Created, student);
            }
            else
            {
                return InternalServerError();
            }
        }
        catch (Exception ex)
        {
            return InternalServerError(ex);
        }
    }

    [HttpPut]
    public IHttpActionResult Put(StudentModel studentModel)
    {
        try
        {
            Student student = transformer.TransformModelToEntity(studentModel);

            if (repository.Update(student))
            {
                return Content(HttpStatusCode.Accepted, studentModel);
            }
            else
            {
                return NotFound();
            }
        }
        catch (Exception ex)
        {
            return InternalServerError(ex);
        }
    }

    [HttpDelete]
    public IHttpActionResult Delete(int Id)
    {
        try
        {
            if(repository.Delete(Id))
            {
                return Ok();
            }
            else
            {
                return NotFound();
            }
        }
        catch (Exception ex)
        {
            return InternalServerError(ex);
        }
    }
}

Мой код класса тестирования

[TestClass]
public class StudentServiceTest
{
    static Mock<ITransformers<StudentModel, Student>> mockTransformer;
    static Mock<IRepository<Student>> mockRepository;

    [ClassInitialize]
    public static void ClassInit(TestContext context)
    {
        mockTransformer = new Mock<ITransformers<StudentModel, Student>>();
        mockRepository = new Mock<IRepository<Student>>();
    }

    //GetAll Tests
    [TestMethod]
    public void GetReturnsAllStudents()
    {
        // Arrange
        IEnumerable<Student> fakeStudents = GetFakeStudents();
        mockRepository.Setup(x => x.Get()).Returns(fakeStudents);
        var controller = new StudentController(mockRepository.Object, mockTransformer.Object);

        // Act
        IHttpActionResult actionResult = controller.Get();
        var contentResult = actionResult as OkNegotiatedContentResult<IEnumerable<Student>>;

        // Assert
        Assert.IsNotNull(contentResult);
        Assert.IsNotNull(contentResult.Content);
        Assert.IsInstanceOfType(contentResult, typeof(OkResult));
        Assert.AreEqual(3, contentResult.Content.Count());
    }

    [TestMethod]
    public void GetReturnsNoContent()
    {
        // Arrange
        var controller = new StudentController(mockRepository.Object, mockTransformer.Object);

        // Act
        IHttpActionResult actionResult = controller.Get();
        StatusCodeResult statusCodeResult = actionResult as StatusCodeResult;

        //Assert
        Assert.IsNotNull(statusCodeResult);
        Assert.AreEqual<HttpStatusCode>(HttpStatusCode.NoContent, statusCodeResult.StatusCode);
    }

    [TestMethod]
    public void GetReturnsException()
    {
        // Arrange
        mockRepository.Setup(x => x.Get()).Throws<Exception>();
        var controller = new StudentController(mockRepository.Object, mockTransformer.Object);

        // Act
        IHttpActionResult actionResult = controller.Get();

        //Assert
        Assert.IsNotNull(actionResult);
        Assert.IsInstanceOfType(actionResult, typeof(ExceptionResult));
    }
    //End of tests GetAll

    //GetById Tests
    [TestMethod]
    public void GetByIdReturnsStudent()
    {
        // Arrange
        IEnumerable<Student> fakeStudents = GetFakeStudents();
        mockRepository.Setup(x => x.GetById(It.IsAny<int>())).Returns(fakeStudents.FirstOrDefault());
        var controller = new StudentController(mockRepository.Object, mockTransformer.Object);

        // Act
        IHttpActionResult actionResult = controller.Get(It.IsAny<int>());
        var contentResult = actionResult as OkNegotiatedContentResult<Student>;

        // Assert
        Assert.IsNotNull(contentResult);
        Assert.IsNotNull(contentResult.Content);
        Assert.AreEqual(1, contentResult.Content.Id);
    }

    [TestMethod]
    public void GetByIdReturnsNotFound()
    {
        // Arrange
        Student student = null;
        mockRepository.Setup(x => x.GetById(It.IsAny<int>())).Returns(student);
        var controller = new StudentController(mockRepository.Object, mockTransformer.Object);

        // Act
        IHttpActionResult actionResult = controller.Get(It.IsAny<int>());

        // Assert
        Assert.IsNotNull(actionResult);
        Assert.IsInstanceOfType(actionResult, typeof(NotFoundResult));
    }

    [TestMethod]
    public void GetByIdReturnsException()
    {
        // Arrange
        mockRepository.Setup(x => x.Get()).Throws<Exception>();
        var controller = new StudentController(mockRepository.Object, mockTransformer.Object);

        // Act
        IHttpActionResult actionResult = controller.Get(It.IsAny<int>());

        //Assert
        Assert.IsNotNull(actionResult);
        Assert.IsInstanceOfType(actionResult, typeof(ExceptionResult));
    }
    //End of GetById tests
}

Пост тестирования дляпроверка кода состояния 201

[TestMethod]     
public void PostReturnsSuccess()
{
        // Arrange
        mockRepository.Setup(x => x.Save(It.IsAny<Student>())).Returns(1);
        mockTransformer.Setup(x => x.TransformModelToEntity(It.IsAny<StudentModel>())).Returns(GetFakeStudents().FirstOrDefault());
        var controller = new StudentController(mockRepository.Object, mockTransformer.Object);

        // Act
        IHttpActionResult actionResult = controller.Post(It.IsAny<StudentModel>());
        var createdResult = actionResult as CreatedNegotiatedContentResult<Student>;
        //var createdResult = actionResult as CreatedAtRouteNegotiatedContentResult<Student>;

        //Assert
        Assert.IsNotNull(actionResult);
        Assert.IsNotNull(createdResult.Content);
        Assert.AreEqual(1, createdResult.Content.Id);
}

Пытался использовать CreatedNegotiatedContentResult и CreatedAtRouteNegotiatedContentResult и сравнивать коды состояния, но у моего actionResult есть исключения для Formatters, ContentNegotiation и Request Properties, и он получает нулевой объект в createdResult.

Дайте мне знать, как проверить код состояния 201?

Обновлено для насмешки BadRequest из CustomFilter

Modelstatevalidationfilter

   public class ModelStateValidationFilter : ActionFilterAttribute
        {
            public override void OnActionExecuting(HttpActionContext actionContext)
            {
                if (!actionContext.ModelState.IsValid)
                {
                    actionContext.Response = actionContext.Request.CreateErrorResponse(
                        HttpStatusCode.BadRequest, actionContext.ModelState);
                }
            }
        }

Метод тестированиядля BadRequest

[TestMethod]
        public void PostReturnsBadRequest()
        {
            // Arrange
            //var mockFilter = new Mock<ModelStateValidationFilter>().Setup(x=>x.OnActionExecuting(It.IsAny<HttpActionContext>()))
            var controller = new StudentController(mockRepository.Object, mockTransformer.Object);

            // Act
            IHttpActionResult actionResult = controller.Post(new StudentModel { Id = 0, FirstName = "Raju", LastName = "", CourseId = 0 });
            var badResult = actionResult as NegotiatedContentResult<Student>;

            //Assert
            Assert.IsNotNull(actionResult);
            Assert.IsInstanceOfType(actionResult, typeof(BadRequestErrorMessageResult));
            //TODO: Check for status code bad request and 
            Assert.IsNotNull(badResult.Content);
            Assert.AreEqual(HttpStatusCode.Created, badResult.StatusCode);
        }

, где в модели требуется фамилия, поэтому API возвращает BadRequest.Но как смоделировать это поведение в модульном тесте?

1 Ответ

0 голосов
/ 13 мая 2018

Метод Post(StudentModel studentModel) возвращает NegotiatedContentResult<T> в случае успеха

return Content(HttpStatusCode.Created, student);

, но тест PostReturnsSuccess пытается преобразовать его в

var createdResult = actionResult as CreatedNegotiatedContentResult<Student>;
//var createdResult = actionResult as CreatedAtRouteNegotiatedContentResult<Student>;

Либо обновите тест досопоставьте ожидаемое от действия, а затем проверьте ожидаемый код состояния

// Act
IHttpActionResult actionResult = controller.Post(It.IsAny<StudentModel>());
var createdResult = actionResult as NegotiatedContentResult<Student>;

//Assert
Assert.IsNotNull(actionResult);
Assert.IsNotNull(createdResult.Content);
Assert.AreEqual(1, createdResult.Content.Id);
Asssert.AreEqual(HttpStatusCode.Created, createdResult.StatusCode); // <-- check status

или обновите действие, чтобы использовать один из Created связанных методов ApiController, который при вызове установил бы код состоянияво время выполнения.

...