我正在尝试为某些类编写测试。我要测试的类使用不同的存储库来从我的数据库中获取和保存内容。
一个简化的例子
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/