使用依赖注入和最小起订量进行单元测试
Unit Testing With Dependency Injection and MOQ
我只是在学习依赖注入和模拟是如何工作的,但我想要一些关于我如何设置几个测试的反馈。我可以让他们通过,但我不确定这是否是我所需要的。
这是一个 MVC 应用程序,它对 return 数据进行 Web API 调用。对于这个例子,我是 运行 Web API 中填充下拉列表的查询。
请给我任何和所有关于我在这里做对或错的建议,或者我应该做的不同的事情。
依赖注入的安装文件 - Unity.WebAPI(NuGet 包)
UnityConfig.cs
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
container.RegisterType<IDropDownDataRepository, DropDownDataRepository>();
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}
控制器
public class DropDownDataController : ApiController
{
private IDropDownDataRepository _dropDownDataRepository;
//Dependency Injection (I'm using Unity.WebAPI)
public DropDownDataController(IDropDownDataRepository dropDownDataRepository)
{
_dropDownDataRepository = dropDownDataRepository;
}
[HttpGet]
public HttpResponseMessage DateList()
{
try
{
return _dropDownDataRepository.DateList();
}
catch
{
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
}
}
}
存储库
public class DropDownDataRepository : IDropDownDataRepository
{
//Is this fine in here, or should it be injected somehow too?
private MyDatabaseEntities db = new MyDatabaseEntities();
public HttpResponseMessage DateList()
{
var sourceQuery = (from p in db.MyProcedure()
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;
}
}
接口
public interface IDropDownDataRepository
{
HttpResponseMessage DateList();
}
单元测试
/// <summary>
/// Tests the DateList method is run
/// I pieced this kind of test together from examples online
/// I'm assuming this is good for a simple test
/// </summary>
[TestMethod]
public void DateListTest1()
{
//Arrange
var mockRepository = new Mock<IDropDownDataRepository>();
mockRepository.Setup(x => x.DateList());
var controller = new DropDownDataController(mockRepository.Object);
//Act
controller.DateList();
//Assert
mockRepository.VerifyAll();
}
/// <summary>
/// Tests the DateList method returns correct status code.
/// This will run with success, but I'm not sure if that's just
/// because I'm telling it to return what I'm expecting.
/// I welcome suggestions for improvement.
/// </summary>
[TestMethod]
public void DateListTest2()
{
//Arrange
var mockRepository = new Mock<IDropDownDataRepository>();
mockRepository
.Setup(x => x.DateList())
//This will only succeed if I have the Returns property here,
//but isn't that just bypassing the actual "test" of whether or
//not this works?
.Returns(new HttpResponseMessage(HttpStatusCode.OK));
DropDownDataController controller = new DropDownDataController(mockRepository.Object);
controller.Request = new HttpRequestMessage();
controller.Configuration = new HttpConfiguration();
//Act
var response = controller.DateList();
//Assert
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}
更新 1
我的主要问题之一是 .Returns
属性 的实际作用。在我的第二个单元测试中,我告诉它 return OK,然后检查它是否 return OK。我看不出这实际上是如何测试任何东西的。
One of my main questions here is what the .Returns property actually
does. In my second unit test, I'm telling it to return OK, then check
if it returns OK. I can't see how that's actually testing anything.
代码:
mockRepository
.Setup(x => x.DateList())
//This will only succeed if I have the Returns property here,
//but isn't that just bypassing the actual "test" of whether or
//not this works?
.Returns(new HttpResponseMessage(HttpStatusCode.OK));
说当 mockRepository
收到对 DateList()
的呼叫时,它应该 return 一个 new HttpResponseMessage(HttpStatusCode.OK)
.
所以里面
[HttpGet]
public HttpResponseMessage DateList()
单元测试到线时
return _dropDownDataRepository.DateList();
模拟对象触发并且 returns new HttpResponseMessage(HttpStatusCode.OK)
此测试的更好名称应该是 DateListTest2
,类似于 DateList_Returns_Status_Code_From_Repository
,因为这就是您在测试中安排的名称。
老实说 controller.DateList()
没有太多逻辑,所以这是你唯一可以拥有的黄金路径测试。
我只是在学习依赖注入和模拟是如何工作的,但我想要一些关于我如何设置几个测试的反馈。我可以让他们通过,但我不确定这是否是我所需要的。
这是一个 MVC 应用程序,它对 return 数据进行 Web API 调用。对于这个例子,我是 运行 Web API 中填充下拉列表的查询。
请给我任何和所有关于我在这里做对或错的建议,或者我应该做的不同的事情。
依赖注入的安装文件 - Unity.WebAPI(NuGet 包)
UnityConfig.cs
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
container.RegisterType<IDropDownDataRepository, DropDownDataRepository>();
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}
控制器
public class DropDownDataController : ApiController
{
private IDropDownDataRepository _dropDownDataRepository;
//Dependency Injection (I'm using Unity.WebAPI)
public DropDownDataController(IDropDownDataRepository dropDownDataRepository)
{
_dropDownDataRepository = dropDownDataRepository;
}
[HttpGet]
public HttpResponseMessage DateList()
{
try
{
return _dropDownDataRepository.DateList();
}
catch
{
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
}
}
}
存储库
public class DropDownDataRepository : IDropDownDataRepository
{
//Is this fine in here, or should it be injected somehow too?
private MyDatabaseEntities db = new MyDatabaseEntities();
public HttpResponseMessage DateList()
{
var sourceQuery = (from p in db.MyProcedure()
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;
}
}
接口
public interface IDropDownDataRepository
{
HttpResponseMessage DateList();
}
单元测试
/// <summary>
/// Tests the DateList method is run
/// I pieced this kind of test together from examples online
/// I'm assuming this is good for a simple test
/// </summary>
[TestMethod]
public void DateListTest1()
{
//Arrange
var mockRepository = new Mock<IDropDownDataRepository>();
mockRepository.Setup(x => x.DateList());
var controller = new DropDownDataController(mockRepository.Object);
//Act
controller.DateList();
//Assert
mockRepository.VerifyAll();
}
/// <summary>
/// Tests the DateList method returns correct status code.
/// This will run with success, but I'm not sure if that's just
/// because I'm telling it to return what I'm expecting.
/// I welcome suggestions for improvement.
/// </summary>
[TestMethod]
public void DateListTest2()
{
//Arrange
var mockRepository = new Mock<IDropDownDataRepository>();
mockRepository
.Setup(x => x.DateList())
//This will only succeed if I have the Returns property here,
//but isn't that just bypassing the actual "test" of whether or
//not this works?
.Returns(new HttpResponseMessage(HttpStatusCode.OK));
DropDownDataController controller = new DropDownDataController(mockRepository.Object);
controller.Request = new HttpRequestMessage();
controller.Configuration = new HttpConfiguration();
//Act
var response = controller.DateList();
//Assert
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}
更新 1
我的主要问题之一是 .Returns
属性 的实际作用。在我的第二个单元测试中,我告诉它 return OK,然后检查它是否 return OK。我看不出这实际上是如何测试任何东西的。
One of my main questions here is what the .Returns property actually does. In my second unit test, I'm telling it to return OK, then check if it returns OK. I can't see how that's actually testing anything.
代码:
mockRepository
.Setup(x => x.DateList())
//This will only succeed if I have the Returns property here,
//but isn't that just bypassing the actual "test" of whether or
//not this works?
.Returns(new HttpResponseMessage(HttpStatusCode.OK));
说当 mockRepository
收到对 DateList()
的呼叫时,它应该 return 一个 new HttpResponseMessage(HttpStatusCode.OK)
.
所以里面
[HttpGet]
public HttpResponseMessage DateList()
单元测试到线时
return _dropDownDataRepository.DateList();
模拟对象触发并且 returns new HttpResponseMessage(HttpStatusCode.OK)
此测试的更好名称应该是 DateListTest2
,类似于 DateList_Returns_Status_Code_From_Repository
,因为这就是您在测试中安排的名称。
老实说 controller.DateList()
没有太多逻辑,所以这是你唯一可以拥有的黄金路径测试。