用假货或嘲笑进行单元测试?

8 tdd unit-testing

我在编写测试套件时试图遵循良好的做法.中途我意识到我花了很多(大部分)时间在假物体上...我的大多数测试都是这样的

public interface ITemplateRepository
{
  string get GetGenericTemplate {get;}
}
Run Code Online (Sandbox Code Playgroud)


public FakeTemplateRepository : ITemplateRepository
{
   public string GetGenericTemplate ()
   {
     return "<xml>Complex</xml>";
   }
}
Run Code Online (Sandbox Code Playgroud)


[Test]
public void CanGetGenericTemplate()
{
  ITemplateRepository rep = new FakeTemplateRepository();
  Assert.IsNotNull(rep.GetGenericTemplate());
}   
Run Code Online (Sandbox Code Playgroud)


[Test]
public void GetGenericTemplateContains()
{  
ITemplateRepository rep = new FakeTemplateRepository();
Assert.IsTrue(rep.GetGenericTemplate().StartsWith("<xml>"));
}
Run Code Online (Sandbox Code Playgroud)

我实际上发现自己花了很多时间在FakeTemplateRepository上,确保它返回了我期待的实际内容.这是坏事吗?

这仍然是有效的单元测试吗?单元测试应该快速而简单,不是吗?但老实说,我不太确定,有一点可以肯定的是,它让我思考了数据的形状和内容.FakeRepository中的内容或多或少会反映我的制作内容,尽管是从文件系统中读取而不是在内存中.

如果事实上我正在做的是集成测试,那么我应该如何使用模拟进行单元测试呢?

对我(如果使用Mocks)我没有意义,我设置了期望,以便它调用方法并返回一个字符串?我错过了什么,但我没有看到太多的价值吗?如果我设置了无效的方法名称,代码甚至不会编译!

我真的对整个事情感到困惑,而且我对单元测试的看法现在已经完全模糊了所有这些概念.

任何人都可以用一个超级简单的例子展示假货和模拟如何融入套房吗?例如什么应该是单元测试,什么应该是集成测试?

谢谢

Gis*_*shu 10

再一次......另一个人陷入模仿反模式.你正在"测试一个模拟"或假对象 - 这根本没用.模拟需要用于抽象测试主题的依赖关系或协作者...而不是测试主题本身.

首先,我要读一下Martin Fowler的论文" Mocks Are not Stubs ".如果您想为特定参数返回值或设置期望值,请选择基于Roll-your-own假货的模拟框架.假货通常用于存在协作者......你不关心协作者......例如存根网络或文件IO.
接下来阅读这个类似的SO问题及其答案..


Phi*_*gan 5

在您的示例中,您正在测试您的假货.你无法理解这一点,因为它没有意义.

这是一个如何使用假货的例子.您想要对DocumentGenerator类进行单元测试.该类碰巧使用ITemplateRepository的服务.但是,要正确地对DocumentGenerator进行单元测试,您需要确保它不依赖于任何外部服务.因此,您为DocumentGenerator提供了一个假的ITemplateRepository,它将返回预制结果.

这是代码的样子.

public class DocumentGenerator
{
  ITemplateRepository _repo;

  DocumentGenerator( ITemplateRepository repo )
  {
    _repo = repo;
  }

  Doc GenerateDoc()
  {
   ....
   _repo.GetGenericTemplate();
    ....
  }
}


[Test]
public void GenerateDocTest()
{
  ITemplateRepository rep = new FakeTemplateRepository();
  DocumentGenerator docGenerator = new DocumentGenerator( rep );
  Assert.IsNotNull(docGenerator.GenerateDoc());
}
Run Code Online (Sandbox Code Playgroud)

该示例的要点是您测试使用假的东西.你没有测试假货本身.假的存在使你正在测试的东西不依赖于外部的东西.