--------请参阅下面的更新,因为我现在已经设置了依赖注入(inject)和 MOQ 模拟框架的使用。我仍然想拆分我的存储库,这样它就不会直接依赖于在同一函数中拉取 windowsUser。
我的 Intranet 站点中有一个 Web API,用于填充下拉列表。下拉列表后面的查询将 Windows 用户名作为参数返回列表。
我意识到我没有正确设置所有这些,因为我无法对其进行单元测试。我需要知道这个“应该”如何设置以允许单元测试,然后单元测试应该是什么样子。
附加信息:这是一个 ASP.NET MVC 5 应用程序。
界面
public interface ITestRepository
{
HttpResponseMessage DropDownList();
}
存储库
public class ExampleRepository : IExampleRepository
{
//Accessing the data through Entity Framework
private MyDatabaseEntities db = new MyDatabaseEntities();
public HttpResponseMessage DropDownList()
{
//Get the current windows user
string windowsUser = HttpContext.Current.User.Identity.Name;
//Pass the parameter to a procedure running a select query
var sourceQuery = (from p in db.spDropDownList(windowsUser)
select p).ToList();
string result = JsonConvert.SerializeObject(sourceQuery);
var response = new HttpResponseMessage();
response.Content = new StringContent(result, System.Text.Encoding.Unicode, "application/json");
return response;
}
}
Controller
public class ExampleController : ApiController
{
private IExampleRepository _exampleRepository;
public ExampleController()
{
_exampleRepository = new ExampleRepository();
}
[HttpGet]
public HttpResponseMessage DropDownList()
{
try
{
return _exampleRepository.DropDownList();
}
catch
{
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
}
}
}
更新1
我已经根据 BartoszKP 的建议更新了我的 Controller 以显示依赖项注入(inject)。
更新 Controller
public class ExampleController : ApiController
{
private IExampleRepository _exampleRepository;
//Dependency Injection
public ExampleController(IExampleRepository exampleRepository)
{
_exampleRepository = exampleRepository;
}
[HttpGet]
public HttpResponseMessage DropDownList()
{
try
{
return _exampleRepository.DropDownList();
}
catch
{
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
}
}
}
更新2
我决定使用 MOQ 作为单元测试的模拟框架。我可以测试一些简单的东西,如下所示。 这将测试一个不带任何参数且不包含 windowsUser 部分的简单方法。
[TestMethod]
public void ExampleOfAnotherTest()
{
//Arrange
var mockRepository = new Mock<IExampleRepository>();
mockRepository
.Setup(x => x.DropDownList())
.Returns(new HttpResponseMessage(HttpStatusCode.OK));
ExampleController controller = new ExampleController(mockRepository.Object);
controller.Request = new HttpRequestMessage();
controller.Configuration = new HttpConfiguration();
//Act
var response = controller.DropDownList();
//Assert
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}
我需要测试 DropDownList 方法的帮助(其中包含获取 windowsUser 的代码)。我需要有关如何分解此方法的建议。我知道这两个部分不应该采用相同的方法。我不知道如何安排拆分 windowsUser 变量。我意识到这确实应该作为参数引入,但我不知道如何实现。
最佳答案
您通常不对存储库进行单元测试(集成测试验证它们是否确实正确地将数据持久保存在数据库中) - 例如参见 this article on MSDN :
Typically, it is difficult to unit test the repositories themselves, so it is often better to write integration tests for them.
所以,让我们专注于仅测试 Controller 。
更改 Controller 以在其构造函数中采用 IExampleRepository
作为参数:
private IExampleRepository _exampleRepository;
public ExampleController(IExampleRepository exampleRepository)
{
_exampleRepository = exampleRepository;
}
然后,在单元测试中,使用模拟框架之一(例如 RhinoMock)创建一个 stub ,其唯一目的是测试 Controller 。
[TestFixture]
public class ExampleTestFixture
{
private IExampleRepository CreateRepositoryStub(fake data)
{
var exampleRepositoryStub = ...; // create the stub with a mocking framework
// make the stub return given fake data
return exampleRepositoryStub;
}
[Test]
public void GivenX_WhenDropDownListIsRequested_ReturnsY()
{
// Arrange
var exampleRepositoryStub = CreateRepositoryStub(X);
var exampleController = new ExampleController(exampleRepositoryStub);
// Act
var result = exampleController.DropDownList();
// Assert
Assert.That(result, Is.Equal(Y));
}
}
这只是一个快速而肮脏的示例 - CreateRepositoryStub
方法当然应该提取到某个测试实用程序类。也许它应该返回一个流畅的界面,以使测试的 Arrange 部分在给定的内容上更具可读性。更像是:
// Arrange
var exampleController
= GivenAController()
.WithFakeData(X);
(当然,使用更好的名称来反射(reflect)您的业务逻辑)。
对于 ASP.NET MVC,框架需要知道如何构造 Controller 。幸运的是,ASP.NET 支持依赖注入(inject)范例,并且当 using MVC unity 时不需要无参数构造函数。 .
另外,请注意 Richard Szalay 的评论:
You shouldn't use
HttpContext.Current
in WebApi - you can usebase.User
which comes fromHttpRequestBase.User
and is mockable. If you really want to continue usingHttpContext.Current
, take a look at Mock HttpContext.Current in Test Init Method
关于c# - 对使用 Windows 身份验证的 Controller 进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34519238/