Integration tests - what would you test for in this controller?
我正在
我在考虑应该测试控制器的哪些部分时遇到了麻烦。 最后,我们希望能够自动化"具有" x"角色的用户能否获取此数据?"
查看此控制器的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | 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)); } } } |
供参考,这是我到目前为止的内容。 我正在定义的某些私有字段不应在此处-当前试图通过
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | 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()); } } } } |
集成测试意味着几件事:
这是一个集成测试,因为它涉及到api和数据库的所有内容。
现在,您说您在确定要测试控制器的哪个部分时遇到了麻烦。这表明您将集成测试与单元测试混淆了。
我们已经介绍过的集成测试。
单元测试涵盖部分功能。您无需测试控制器,就不用管它了。
您真正需要考虑的是:
首先,将代码与控制器分开。保持控制器非常基础。它接收一个调用,验证请求模型,并将其进一步传递到功能发生的类库。这样您就可以忘记"测试控制器",而专注于功能。单元测试将对您有所帮助,您的测试用例将变成这样
有了这样的设置,您可以按自己喜欢的方式设置测试数据并检查每个测试用例。
您想知道如何测试控制器的唯一原因是因为您将所有代码都转储到了控制器中,这当然会使一切变得困难。想想SOLID,想想SOC(关注点分离)。
一条建议:永远不要从终结点返回IQueryable,这不是数据,只是一个尚未运行的查询。无论您需要什么,都返回一个List,IEnumerable,一个奇异对象,只需确保首先通过例如在IQueryable表达式上调用ToList()来首先执行该列表即可。
因此,步骤如下: