失去理智单元测试

时间:2012-08-08 12:17:32

标签: unit-testing repository-pattern

因为我没有理解单元测试。

我有服务

public interface IMyService
{
    public List<Person> GetRandomPeople();
}

然后在我的MVC项目中我实现了这项服务

public MyService : IMyService
{
    public List<Person> GetRandomPeople();
    {
         ...the actual logic the get the People here. This is what i want to test ?
    }
}

然后在我的控制器中

public HomeController : Controller
{
     IMyService _myService;
     public HomeController(IMyService myService)
     {
         _myService = myService
     }
}

然后在Action方法中我将使用

public ActionResult CreateRandom()
{
    List<Person> people = _myService.GetRandomPeople();
    return View(people)
}

注意:人员回购是我的服务,只是快速输入,所以我有一个回购。

我的问题:如何在我的测试项目中测试我的服务实现。我现在真的被困住了,我认为这将是我TDD未来的“光明”时刻。

提前感谢。

1 个答案:

答案 0 :(得分:2)

将服务接口注入控制器的目的是让您单独测试控制器。要测试它,你传入一个模拟或伪造的IMyService。

根据您的服务实施方式,您可能需要使用集成测试来测试服务。这些应该与您的单元测试分开(因为您不想连续运行它们)。

例如,假设IMyService是使用Entity Framework实现的。您需要实际针对数据库运行LINQ to Entities来测试它。您可以使用本地数据库,您可以在EF中创建和填充数据库等等。这些不是单元测试(它们使用I / O),但它们仍然很重要。

其他持久性框架可能允许您针对内存中的数据集进行测试。没关系;我仍然会考虑进行集成测试(您的代码+框架),并将其与您的单元测试分开。

诀窍是将业务逻辑保持在服务实现之外。限制(尽可能)纯数据访问代码。您希望使用单元测试来测试业务逻辑。

修改

要在注释中解决问题(“当您需要创建存根时”):

当你有一个你想要独立测试的类(被测系统或SUT)并且该类已注入依赖项时,你可以创建存根,假货,测试双打或模拟(有很多术语)。 / p>

这些依赖关系将以某种方式呈现为抽象 - 接口,抽象类,具有虚方法的类,委托等。

您的生产代码将传递具体实现(例如,击中数据库的类)。您的测试代码将通过测试实现。

您可以传递一个简单的存根实现(只需在您的测试项目中编写一个实现接口并为其成员返回固定值的虚拟类),或者您可以拥有一个更好的实现来检测调用的内容和参数传递(模拟对象)。你可以手工编写所有这些。它变得乏味,因此许多测试人员使用模拟对象框架(也称为隔离框架)。这些中有很多(通常是几种语言);我倾向于在.NET中使用NSubstituteMoq

学习编写测试需要时间。阅读有关该主题的几本书对我帮助很大。博客文章可能没有提供足够的背景(遗憾地关闭)question here中有一些很好的建议。

简短的回答是,当您的测试需要时,您可以创建存根或模拟。