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



我正在.NET Web API 2项目中的控制器端点上应用NUnit集成测试,该项目的模型和控制器是通过Entitycode 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. 您可以在数据库中设置测试数据,例如通过脚本
  2. 调用测试中的端点时,您确切地知道应该使用什么数据进行调用以及应该得到什么。这一切都是基于您在步骤1中设置的测试数据
  3. 你将你的预期数据与你得到的数据进行比较

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

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

我们已经介绍了集成测试。单元测试涵盖了部分功能。你不测试控制器,忘了这一点。

你真正需要考虑的是:

首先,将代码与控制器分离。保持控制器非常基本。它接收一个调用,验证请求模型,并将其进一步传递到一个类库,在该类库中执行功能。这可以让您忘记"测试控制器",而是专注于您的功能。单元测试将在这里有所帮助,您的测试用例将变成类似于的东西

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

有了这样的设置,您可以随心所欲地设置测试数据,并检查每个测试用例。

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

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

因此,步骤如下:

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

最新更新