集成测试-您将在此控制器中测试什么?

时间:2018-10-26 19:01:01

标签: c# .net unit-testing nunit integration-testing

我正在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 :(得分:1)

集成测试意味着几件事:

  1. 例如,通过脚本在数据库中设置测试数据。
  2. 您可以调用被测端点,确切知道应该使用什么数据以及应该获得什么数据。这全部基于您在步骤1中设置的测试数据。
  3. 您将预期数据与返回的数据进行比较。

这是一个集成测试,因为它涉及到api和数据库的所有内容。

现在,您说您在确定要测试控制器的哪个部分时遇到了麻烦。这表明您将集成测试与单元测试混淆了。

我们已经介绍过的集成测试。 单元测试涵盖部分功能。您无需测试控制器,就不用管它了。

您真正需要考虑的是:

首先,将您的代码与控制器分开。保持控制器非常基础。它接收一个调用,验证请求模型,并将其进一步传递到功能发生的类库。这样您就可以忘记“测试控制器”,而专注于功能。单元测试将对您有所帮助,您的测试用例将变成这样

  1. 我有一个用户,以某种方式设置。
  2. 我有一些数据,是以某种方式设置的
  3. 当我调用方法X时,我应该得到这个响应。

有了这样的设置,您可以按自己喜欢的方式设置测试数据并检查每个测试用例。

您想知道如何测试控制器的唯一原因是因为您将所有代码都转储到了控制器中,这当然会使一切变得困难。想想SOLID,想想SOC(关注点分离)。

一条建议:永远不要从端点返回IQueryable,这不是数据,仅仅是一个尚未运行的查询。返回列表,IEnumerable,单个对象,无论您需要什么,只需确保首先通过例如在IQueryable表达式上调用ToList()即可首先执行该列表。

因此,步骤如下:

  1. 首先设置您的IQueryable
  2. 通过调用适当的ToList(),First(),FirstOrDefault()并返回其结果来执行它。