【问题标题】:Unit Testing With Dependency Injection and MOQ使用依赖注入和 MOQ 进行单元测试
【发布时间】:2016-01-05 16:09:38
【问题描述】:

我只是在学习依赖注入和模拟是如何工作的,但我想要一些关于我如何设置几个测试的反馈。我可以让他们通过,但我不确定这就是我所需要的。

这是一个 MVC 应用程序,它通过 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 属性实际上做了什么。在我的第二个单元测试中,我告诉它返回 OK,然后检查它是否返回 OK。我看不出这实际上是如何测试任何东西的。

【问题讨论】:

  • 也许最好把这个问题发到codereview
  • 谢谢。我从来不知道它存在,但我也会在那里尝试。

标签: asp.net-mvc unit-testing mocking unity-container moq


【解决方案1】:

我的主要问题之一是 .Returns 属性实际上是什么 做。在我的第二个单元测试中,我告诉它返回 OK,然后检查 如果返回确定。我看不出这实际上是如何测试任何东西的。

代码:

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() 的调用时,它应该返回new HttpResponseMessage(HttpStatusCode.OK)

所以里面

    [HttpGet]
    public HttpResponseMessage DateList()

当单元测试到达该行时

return _dropDownDataRepository.DateList();

模拟对象触发并返回new HttpResponseMessage(HttpStatusCode.OK)

此测试的更好名称是 DateListTest2,而不是 DateList_Returns_Status_Code_From_Repository,因为这是您在测试中安排的名称。

老实说,controller.DateList() 没有太多逻辑,所以这是您可以进行的唯一黄金路径测试。

【讨论】:

  • 感谢您的回答。我有另一个基于相同设置的设置,但涉及 Windows 身份验证稍微复杂一些。如果您能看一看,我将不胜感激。 stackoverflow.com/questions/34519238/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-03
  • 1970-01-01
  • 2021-06-19
  • 1970-01-01
相关资源
最近更新 更多