1

因为我不了解单元测试。

我有服务

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
     }
}

然后在我将使用的操作方法中

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

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

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

提前致谢。

4

1 回答 1

2

将服务接口注入控制器的目的是让您可以单独测试控制器。为了测试它,你传入一个模拟或假的 IMyService。

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

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

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

诀窍是将业务逻辑排除在服务实现之外。将其(尽可能)限制为纯数据访问代码。你想用单元测试来测试你的业务逻辑。

编辑:

要解决评论中的问题(“何时需要创建存根”):

当您有一个要单独测试的类(被测系统或 SUT)并且该类已注入依赖项时,您会创建存根、伪造品、测试替身或模拟(有很多术语)。

这些依赖项将以某种方式是抽象的——接口、抽象类、具有虚拟方法的类、委托等。

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

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

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

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

于 2012-08-08T13:15:46.107 回答