c# - 使用 stub 和模拟进行单元测试

标签 c# unit-testing

我正在尝试为某些类编写测试。我要测试的类使用不同的存储库来从我的数据库中获取和保存内容。

一个简化的例子

public class MyClass
{
    private readonly IGroupRepository _groupRepo;

  public MyClass(IGroupRepository groupRepo){ 
    _groupRepo = groupRepo; 
  }

  public void Execute(PersonInfo personInfo, string id){
  var group = _groupRepo.GetById(id);

  var person = group.Persons.First(p=> p.Id == personInfo.Id);

  person.FirstName = personInfo.FirstName;
  person.LastName = personInfo.LastName;

  _groupRepo.Save(group);      
  }
}

我想做的是确保保存到数据库中的内容是正确的。

所以我有一个这样的单元测试:

[TestMethod]
public void TestMethod(){
    var groupId = "ABC";
    var personId = 1;

    ver personInfo = new PersonInfo()
    {
      Id = personId,
      FirstName = "Sam",
      LastName = "Smith"  
    }

    var groupStub = new Mock<IGroupRepository>;
    groupStub.Setup(x=> x.GetById(groupId)).Returns(new Group(){
            Id = groupId,
            Persons = List<Person>()
            {
                new Person()
                {
                    Id = personId,
                    FirstName = "George",
                    LastName = "Bolton",
                }
            }
        }
    });

    var myClass = new MyClass();
    myClass.Execute(personInfo, groupId);

    var group = groupStub.GetById(groupId);
    var person = group.Persons.First(p=> p.Id == personId);

    Assert.AreEqual(personInfo.FirstName, person.FirstName);
}

我认为这很好,但后来我阅读了更多关于它的内容,我读到你不应该在 sub 上断言,我想我在我的 assert 语句中这样做?我从 stub 中获取信息,然后对结果使用断言?

所以我不确定这是否是正确的测试方法。如果不是,为什么以及正确的方法是什么?

最佳答案

是的,您是正确的,测试的编写方式有问题。事实上,您并不是在测试 MyClass。您正在测试 您使用的模拟框架有效。作为证明,注释使用 MyClass 的两行并再次运行测试。它仍然会通过:

[TestMethod]
public void TestMethod()
{
    var groupId = "ABC";
    var personId = 1;

    ver personInfo = new PersonInfo()
    {
      Id = personId,
      FirstName = "Sam",
      LastName = "Smith"  `
    }

    var groupStub = new Mock<IGroupRepository>;
    groupStub.Setup(x=> x.GetById(groupId)).Returns(new Group(){
            Id = groupId,
            Persons = List<Person>()
            {
                new Person()
                {
                    Id = personId,
                    FirstName = "George",
                    LastName = "Bolton",
                }
            }
        }
    });

    // var myClass = new MyClass();
    // myClass.Execute(personInfo, groupId);

    var group = groupStub.GetById(groupId);
    var person = group.Persons.First(p=> p.Id == personId);

    Assert.AreEqual(personInfo.FirstName, person.FirstName);
}

通常帮助我编写单元测试的是首先问自己我真正测试的是什么行为。在这种特殊情况下,我相信您想在调用 MyClass.Execute 时进行测试, 您希望调用 IGroupRepository.Save 时人名已更改。

在我熟悉的模拟框架 (NSubstitute) 中编写该断言,如下所示:

groupStub.Received().Save(
    Arg.Is<Group>(group =>
    {
        return groupId.Id == groupId && 
            group.Persons[0].Id == personId &&
            group.Persons[0].FirstName == "Sam" &&
            group.Persons[0].LastName == "Smith";
    });

您使用的模拟框架中应该有类似的东西。

关于c# - 使用 stub 和模拟进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44449410/

相关文章:

javascript - Jest 模拟 documentElement lang 属性

swift - Xcode从命令行执行 “Test”?

java - Java 的 nBuilder 替代品

c# - ASP NET Boilerplate > 使用 swagger 代码生成工具 (nswag) 生成 C# swagger 客户端不起作用

java - 如何在 TestNG 中动态更改 @Test 方法

python - PyUnit 中是否弃用了测试套件?

c# - AJAX HtmlEditorExtender 并从文本框中获取文本?

c# - GetCustomAttributes 性能问题(表达式树是解决方案??)

c# - 如何解决 ERROR : Key cannot be null. 参数名称 : key in c#?

c# - NHibernate 的 cfg.xml 文件的单声道验证