Интеграционные тесты - что бы вы тестировали в этом контроллере? - PullRequest
0 голосов
/ 26 октября 2018

Я применяю NUnit интеграционные тесты на наших конечных точках контроллеров в .NET Web API 2 проекте, модели и контроллеры которого генерируются с помощью Entity code first from database.

.части контроллера я должен проверить. В конце мы просто хотели бы иметь возможность "может ли пользователь с ролью" x "получить эти данные?"

Просмотр в GET часть этого контроллера, какие части вы бы протестировали и каковы ваши аргументы?

namespace api.Controllers.myNamespace
{

    public class myController : ApiController
    {
        private string strUserName;
        private string strError = "";
        private string strApiName = "myTable";
        private myDatabase db = new myDatabase();

        // ----------------------------------------------------------------------

        // GET: api/path
        public IQueryable<myTable> GetmyTable()
        {
            try
            {
                this.strUserName = this.getUserName();

                if
                (
                    // ----- authorize -----
                    db.view_jnc_role_api_permission.Count
                    (
                        view =>
                        (
                            view.permission == "get"
                            && view.apiName == this.strApiName
                            && view.userName == this.strUserName
                        )
                    ) == 1
                // ----- /authorize -----
                )
                {
                    // ----- get -----
                    IQueryable<myTable> data =

                    from tbl in db.myTable

                    where tbl.deleted == null

                    select tbl;
                    // ----- /get -----

                    return data;
                }
                else
                {
                    strError = "Unauthorized.";
                    throw new HttpResponseException(HttpStatusCode.Forbidden);
                }
            }
            catch (Exception ex)
            {
                if (strError.Length == 0)
                {
                    if (this.showException())
                    {
                        strError = ex.ToString();
                    }
                }

                throw new HttpResponseException(ControllerContext.Request.CreateErrorResponse(HttpStatusCode.Forbidden, strError));
            }
        }

}

Для справки вот что у меня так далеко.Некоторые из этих закрытых полей, которые я определяю, не должны быть здесь - в настоящее время я пытаюсь получить доступ к закрытым методам из моего тестового проекта через AssemblyInfo.cs, чтобы исправить это:

namespace api.myNamespace
{
        [TestFixture]
        public class myController : ApiController
        {
            private string strUserName;
            private string strError = "";
            private string strApiName = "myTable";
            private myDb db = new myDb();
            // Using TransactionScope to (hopefully) prevent integration test's changes to database from persisting
            protected TransactionScope TransactionScope;
            // Instantiate _controller field
            private myController _controller;

            [SetUp]
            public void SetUp() {
                TransactionScope = new TransactionScope(TransactionScopeOption.RequiresNew);
                // It's possible that one test may leave some state which could impact subsequent tests - so we must reinstantiate _controller at the start of each new test:
                _controller = new myController();
            }

            [TearDown]
            public void TearDown()
            {
                TransactionScope.Dispose();
            }



            **//------ TESTS -------//
            // CanSetAndGetUserName
            // AuthorizedUserCanGetData
            // UnauthorizedUserCannotGetData
            // AuthorizedUserCanPutData
            // UnauthorizedUserCannotPutData
            // AuthorizedUserCanPostData
            // UnauthorizedUserCannotPostData
            // AuthorizedUserCanDeleteData
            // UnauthorizedUserCannotDeleteData**

            [Test]
            public void CanGetAndSetUsername()
            {
            // ARRANGE
            var user = _controller.getUserName();

            // ACT

            // ASSERT
            Assert.That(user, Is.EqualTo("my-internal-username"));
            }

        [Test]
        public void UnauthorizedUserCannotGetData()
        {
            var user = "Mr Unauthorized";
            // Unfinished bc integration testing is super abstract, subjective, hard, time consuming and hard. All downvoters are plebs.
            Assert.That(user, Is.EqualTo());

        }
            }
    }

}

1 Ответ

0 голосов
/ 26 октября 2018

интеграционные тесты означают несколько вещей:

  1. вы настраиваете свои тестовые данные в базе данных, например, с помощью сценария.
  2. вы вызываете тестируемую конечную точку, точно зная, какие данные выследует позвонить с и что вы должны получить.Все это основано на ваших тестовых данных, которые вы настроили на шаге 1.
  3. вы сравниваете ожидаемые данные с теми, которые вы вернули.

это интеграционный тест, поскольку он затрагивает всеи API, и база данных.

Итак, вы сказали, что не можете решить, какие части контроллера проверить.Это говорит о том, что вы путаете интеграционные тесты с юнит-тестами.

Интеграционные тесты, которые мы уже рассмотрели.Модульные тесты охватывают части функциональности.Вы не тестируете контроллеры, забудьте об этом.

Что вам действительно нужно рассмотреть, так это:

Сначала отделите свой код от контроллера.Держите контроллер очень простой.Он принимает вызов, проверяет модель запроса и передает его дальше в библиотеку классов, где происходит функциональность.Это позволяет вам забыть «тестирование контроллера» и сосредоточиться на своей функциональности.Здесь помогут модульные тесты, и ваши тесты станут примерно такими:

  1. У меня есть пользователь, настроенный определенным образом.
  2. У меня есть некоторые данные, настроенные вопределенным образом
  3. Когда я вызываю метод X, тогда я должен получить этот ответ.

Имея такую ​​настройку, вы можете устанавливать свои тестовые данные любым способом и проверять каждыйодин тестовый случай.

Единственная причина, по которой вы задаетесь вопросом, как вы тестируете свой контроллер, заключается в том, что вы сбросили в него весь свой код, что, конечно, усложняет задачу.Думайте SOLID, думайте SOC (Разделение проблем).

Один совет: никогда не возвращайте IQueryable из конечной точки, это не данные, это просто запрос, который еще не запущен.Верните List, IEnumerable, единственный объект, что бы вам ни понадобилось, просто убедитесь, что вы выполняете это сначала, вызывая ToList (), например, для вашего выражения IQueryable.

Итак, шаги выглядят следующим образом:

  1. Сначала настройте свой IQueryable
  2. Выполните его, вызвав ToList (), First (), FirstOrDefault (), что бы это ни былоприсвоить и вернуть результат этого.
...