C#Web Api单元测试和模拟控制器

时间:2012-08-03 19:47:38

标签: c# unit-testing asp.net-web-api moq xunit

我正在研究这个WebAPI项目,我需要为它创建单元测试。项目的基础是使用VS 2010创建的,然后添加了WebApi模块。

控制器的工作方式有点妨碍测试/嘲笑。我正在使用xUnit和Moq,但绝对没有必要坚持使用这两个。

应用程序使用特定对象来处理数据库访问,所以我有 controllerObject及其构造函数需要DataAccessObject

我在模拟控制器/ dataaccess对时遇到问题。我试图运行的第一个测试是一个GetAllFromDataBase,但我真的不知道如何做到这一点。

编辑:

我做了Cuong Le告诉我的事情,整个现在正在移动,我真的很感激它。但我难以接受另一个问题。要访问API,有一个用户名/密码对,我的控制器使用Thread.CurrentPrincipal.Identity.Name;现在我需要设置这个值才能完全正常工作。

还有valueServiceMock.Setup(service => service.GetValues())             .Returns(new [] {“value1”,“value2”});

似乎没有用。当代码试图访问数据库时,由于无法获得有效的用户名来查找

,因此无法获取任何内容

1 个答案:

答案 0 :(得分:20)

为了让您的应用程序可测试,您需要设计可测试性。从技术上讲,为了设计可测试性,您的应用程序应尽可能在层之间,组件之间甚至类之间进行松散耦合。

为可测试性设计了很多提示:避免使用密封的静态类......但是你最需要注意的是dependency injection pattern,而不是在其他对象的构造函数或方法中创建对象,应该注入这个对象。通过这种方式,我们可以通过模拟框架轻松地在类之间依赖。 Esp,用于依赖外部资源的对象:网络,文件或数据库。

如何使用依赖注入注入对象:这就是为什么IocContainer是正确的工具,它将自动为您注入对象。我更喜欢使用的IoC容器是:AutofacNInject

此处将ValueService注入ValuesController的示例:

public class ValuesController : ApiController
{
    private readonly IValueService _valueService;

    public ValuesController(IValueService valueService)
    {
        _valueService = valueService;
    }

    public string[] Get()
    {
        return _valueService.GetValues();
    }

    public string Get(int id)
    {
        return _valueService.GetValue(id);
    }
}

以下是使用Moq进行单元测试的简单代码:

var valueServiceMock = new Mock<IValueService>();
valueServiceMock.Setup(service => service.GetValues())
            .Returns(new[] { "value1", "value2" });

var controller = new ValuesController(valueServiceMock.Object);
var values = controller.Get();

Assert.AreEqual(values.Length, 2);
Assert.AreEqual(values[0], "value1");
Assert.AreEqual(values[1], "value2");