【问题标题】:Mocking Domain Model & Building Tests Without Repetition模拟领域模型和构建测试而不重复
【发布时间】:2014-08-01 09:59:32
【问题描述】:

寻找有关测试的一些说明。我的服务层中有以下方法:

readonly IDomainModelRepository domainModelRepository;

public DomainModelDetailsDto Edit(int DomainModelID, IPrincipal User)
{
    DomainModel myDomainModel = domainModelRepository.Find(DomainModelID);
    if ((myDomainModel == null) || (!myDomainModel.UserCanEdit(User)))
        throw new UnauthorisedException();

    // Other stuff here...
}

现在我正在构建一套测试,但遇到了一些障碍。

  1. 不能模拟对myDomainModel.UserCanEdit(User) 的调用,因为 DomainModel 没有实现任何接口。它变得更加复杂,因为 UserCanEdit 中包含的逻辑实际上会检查其图表中其他域模型上的字段。那么如何轻松设置它以返回设置值以允许我测试服务?
  2. 我正在测试如果 repo 没有找到 DomainModel 项,该方法是否正确响应。然后,如果用户无法编辑,我会测试它是否正确响应(当我解决上面的第 1 点时我会这样做!)。但在那之后,我为“这里的其他东西”编写的每个测试都要求我正确设置测试以通过前两项检查。这看起来很麻烦,并且使每个测试都重复相同的代码。有没有更好的方法?

也许问题在于我的代码本身需要重构,以便于测试。如果是这样,所有建议表示赞赏!

【问题讨论】:

    标签: c# unit-testing testing mocking


    【解决方案1】:

    如果你想测试我认为你需要在myDomainModel 上使用一个接口,否则你不能模拟它。

    我知道这是一个非常有争议的观点,但越来越多的人认为存储库模式是一种反模式,因为它产生的问题多于解决的问题。

    我个人使用实体框架并更改 TT 文件来生成上下文和界面,而不是在我的所有应用程序中我只使用界面。

    为了测试,我只是模拟了界面,我可以测试一切。我所做的更改之一是将所有DbSet<T> 更改为IDbSet<T>。最后,我创建了一个测试助手,其函数接收ObservableCollection 并返回IDbSet,我能够验证所有内容。

    【讨论】:

      【解决方案2】:

      您可以存根UserCanEdit,方法是使用该方法virtual 并拥有一个覆盖它的派生测试类。然后,您的模拟存储库可以返回此测试类集的实例,以根据您要测试的内容返回 true 或 false。

      【讨论】:

      • 将方法标记为虚拟有什么缺点吗?另外,纯粹为了方便测试而更改签名是一种好习惯吗?
      • 在性能等方面将方法标记为虚拟并没有真正的缺点。例如,实体框架要求所有导航属性都是虚拟的。对于纯粹为了方便测试而进行更改有不同的看法,但我个人对此没有意见。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-20
      • 2012-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多