集成测试-您将在此控制器中测试什么? [英] Integration tests - what would you test for in this controller?

查看:202
本文介绍了集成测试-您将在此控制器中测试什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在.NET Web API 2项目的控制器端点上应用NUnit集成测试,该项目的模型和控制器是通过Entity code first from database生成的.

I'm applying NUnit integration tests on our controller endpoints in a .NET Web API 2 project whose models and controllers are generated via Entity code first from database.

我在思考应该测试控制器的哪些部分时遇到了麻烦. 最后,我们希望能够自动化具有"x"角色的用户可以获取此数据吗?"

I'm having trouble thinking of what parts of the controller I should test. In the end, we'd just like to be able to automate "can a user with "x" role get this data?"

查看此控制器的GET部分,您要测试哪些部分,您的推理是什么?

Looking in the GET portion of this controller, what parts would you test and what's your reasoning?

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从我的测试项目中访问私有方法来解决此问题:


For reference, here's what I have so far. Some of these private fields I'm defining shouldn't be here - currently trying to get access to private methods from my test project via AssemblyInfo.cs to fix this:

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());

        }
            }
    }

}

推荐答案

集成测试意味着几件事:

integration tests means several things:

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

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

this is an integration test as it touches everything, both api and database.

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

Now, you said you are having trouble deciding which parts of the controller to test. This suggests you are confusing integration tests with unit tests.

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

Integration tests we already covered. Unit tests cover parts of functionality. You do not test controllers, forget about that.

您真正需要考虑的是:

首先,将您的代码与控制器分开.保持控制器非常基础.它接收一个调用,验证请求模型,然后将其进一步传递到发生功能的类库.这样您就可以忘记测试控制器",而将精力集中在功能上.单元测试将对您有所帮助,您的测试用例将变成这样

First, separate your code from the controller. Keep the controller very basic. It receives a call, validates the request model and passes it further to a class library where the functionality happens. This allows you to forget "testing the controller" and focus on your functionality instead. Unit tests will help here and your test cases will become something like this

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

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

With such a setup in place, you can set your test data any way you like and check every single test case.

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

The only reason you wonder how you test your controller is because you dumped all your code into it, which of course makes everything hard. Think SOLID, think SOC ( Separation of concerns ).

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

One piece of advice: never ever return IQueryable from an endpoint, that's not data, that simply a query that hasn't run yet. Return a List, IEnumerable, an singular object, whatever you need, just make sure you execute that first by calling ToList() for example on your IQueryable expression first.

因此,步骤如下:

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

这篇关于集成测试-您将在此控制器中测试什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆