Unit testing 迷失自我单元测试

Unit testing 迷失自我单元测试,unit-testing,repository-pattern,Unit Testing,Repository Pattern,因为我不了解单元测试 我有服务 public interface IMyService { public List<Person> GetRandomPeople(); } 然后在动作方法上我会用到 public ActionResult CreateRandom() { List<Person> people = _myService.GetRandomPeople(); return View(people) } public Action

因为我不了解单元测试

我有服务

public interface IMyService
{
    public List<Person> GetRandomPeople();
}
然后在动作方法上我会用到

public ActionResult CreateRandom()
{
    List<Person> people = _myService.GetRandomPeople();
    return View(people)
}
public ActionResult CreateRandom()
{
List people=\u myService.GetRandomPeople();
返回视图(人)
}
注意:我的服务对象是回购人,只要快速打印出来,我就有了回购

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


提前感谢。

将服务接口注入控制器的目的是允许您单独测试控制器。为了测试这一点,您通过了一个模拟或假IMyService

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

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

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

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

编辑:

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

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

这些依赖关系在某种程度上是抽象的——接口、抽象类、具有虚拟方法的类、委托等等

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

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

学习编写测试需要时间。读了几本关于这个主题的书对我帮助很大。博客文章可能无法提供足够的背景信息。报告中有一些很好的建议(可悲的是,已经结束了)


简而言之,当测试需要存根或模拟时,您可以创建存根或模拟。

我不理解您的问题
MyService
是一个普通的类,所以就这样测试它吧;我会考虑这个问题。对于刚刚接触单元测试、存储库模式和依赖项注入的开发人员来说,这是一个常见的问题。记住,这是最重要的。:)请你把你的MyService代码贴在这里,为什么你不能测试?顺便说一下,我会返回IEnumerable而不是List。列表是一个实现细节。通过EF,可以使用模拟上下文生成器来促进单元测试:@JakubKaleta-有趣的链接。我认为需要集成测试来进行验证。只是完全搞不清楚什么时候需要创建存根等等。
public HomeController : Controller
{
     IMyService _myService;
     public HomeController(IMyService myService)
     {
         _myService = myService
     }
}
public ActionResult CreateRandom()
{
    List<Person> people = _myService.GetRandomPeople();
    return View(people)
}