单元测试和nhibernate?

cho*_*bo2 9 c# nhibernate unit-testing moq fluent-nhibernate

我想知道如何解决这个问题.我正在使用nhibernate和流利.

我有这样的域类

public class User
{
   public virtual int UserId {get; private set;}
}
Run Code Online (Sandbox Code Playgroud)

这似乎是做nhibernate的惯例,因为它会阻止人们设置和id,因为它是自动生成的.

现在问题出现在我进行单元测试时.

我把我所有的nhibernate代码都放在了一个我模拟出来的repo中,所以我只测试我的服务层.发生这种情况时会出现问题.

User user = repo.GetUser(email);
Run Code Online (Sandbox Code Playgroud)

这应该返回一个用户对象.

所以我想用moq来做这件事

repo.Setup(x => x.GetUser(It.IsAny<string>())).Return(/* UserObject here */)
Run Code Online (Sandbox Code Playgroud)

现在这是问题所在

我需要创建User对象并将其放在Return部分中.

所以我会做类似的事情

User user =  new User()
{
   UserId = 10,
}
Run Code Online (Sandbox Code Playgroud)

但这就是问题所在,我需要设置Id,因为我实际上在以后使用它来对某些集合做一些linq(在服务层,因为它没有击中我的数据库所以它不应该在我的仓库中)所以我需要设置它,但我无法设置它,因为它是一个私人集.

所以我该怎么做?我应该删除私人还是有其他方式?

Enr*_*lio 15

你可以让假Repository对象返回一个假User对象:

var stubUser = new Mock<User>();
stubUser.Setup(s => s.UserId).Returns(10);

var stubRepo = new Mock<IUserRepository>();
stubRepo.Setup(s => s.GetUser(It.IsAny<string>())).Return(stubUser);
Run Code Online (Sandbox Code Playgroud)

这里有几点需要注意:

  1. 如果将Moq标记为虚拟,则Moq只能伪造具体类的成员.这可能不适用于某些情况,在这种情况下,通过Moq伪造对象的唯一方法是让它实现一个接口.
    但是,在这种情况下,解决方案很好地工作,因为NHibernate已经对User类的属性施加了相同的要求以便进行延迟加载.
  2. 假物品返回其他假货有时可能导致超过指定的单位测试.在这些情况下,由存根和模拟组成的丰富对象模型的构建增长到难以确定究竟正在测试什么的程度,使得测试本身难以理解且难以维护.这是一个非常精细的单元测试实践,要清楚,但必须有意识地使用它.

相关资源: