代码之家  ›  专栏  ›  技术社区  ›  Kyle Vassella

集成测试-您在这个控制器中测试什么?

  •  -1
  • Kyle Vassella  · 技术社区  · 6 年前

    我正在申请 NUnit .NET Web API 2 其模型和控制器通过 Entity code first from database .

    我想不出该测试控制器的哪些部分。 最后,我们希望能够实现自动化

    往里看 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 回复  |  直到 6 年前
        1
  •  1
  •   Andrei Dragotoniu    6 年前

    集成测试意味着以下几点:

    1. 例如,可以通过脚本在数据库中设置测试数据。
    2. 您调用被测端点,知道应该用什么数据调用它以及应该得到什么。这完全基于您在步骤1中设置的测试数据。

    这是一个集成测试,因为它涉及到一切,包括api和数据库。

    现在,你说你很难决定要测试控制器的哪个部分。这表明您混淆了集成测试和单元测试。

    我们已经讨论过的集成测试。 单元测试包括部分功能。你不测试控制器,忘了这个。

    你真正需要考虑的是:

    首先,将代码与控制器分离。保持控制器非常基本。它接收一个调用,验证请求模型,并将其进一步传递到发生功能的类库。这让你忘记了“测试控制器”,转而专注于你的功能。单元测试在这里会有帮助,你的测试用例会变成这样

    1. 我有一个用户,以某种方式设置。
    2. 我有一些数据,是以某种方式建立的

    有了这样的设置,您可以任意设置测试数据并检查每个测试用例。

    你想知道如何测试你的控制器的唯一原因是你把所有的代码都扔进了控制器,这当然会让一切变得困难。好好想想,想想SOC(关注点的分离)。

    一条建议是:永远不要从端点返回IQueryable,这不是数据,只是一个还没有运行的查询。返回一个List,IEnumerable,一个单独的对象,不管你需要什么,只要确保你首先执行它,比如首先在你的IQueryable表达式上调用ToList()就可以了。

    所以,步骤如下:

    1. 通过调用ToList()、First()、FirstOrDefault()执行它,并返回结果。