C# 使用存根和模拟进行单元测试
我正在为一些类编写测试。我要测试的类使用不同的存储库从数据库中获取和保存内容 一个简化的例子C# 使用存根和模拟进行单元测试,c#,unit-testing,C#,Unit Testing,我正在为一些类编写测试。我要测试的类使用不同的存储库从数据库中获取和保存内容 一个简化的例子 public class MyClass { private readonly IGroupRepository _groupRepo; public MyClass(IGroupRepository groupRepo){ _groupRepo = groupRepo; } public void Execute(PersonInfo personInfo, str
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);
}
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";
});
[TestMethod]
公共void TestMethod(){
var groupId=“ABC”;
变量personId=1;
ver personInfo=新personInfo()
{
Id=人形,
FirstName=“山姆”,
LastName=“史密斯”
}
var groupStub=新模拟;
groupStub.Setup(x=>x.GetById(groupId)).Returns(newgroup()){
Id=groupId,
人员=名单()
{
新人()
{
Id=人形,
FirstName=“乔治”,
LastName=“博尔顿”,
}
}
}
});
var 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);
}
我认为这很好,但后来我读了更多关于它的内容,我读到你不应该在潜艇上断言,我想我在我的断言声明中是这样做的?我从存根中获取信息,然后对结果使用断言
所以我不确定这是否是正确的测试方法。如果没有,为什么以及正确的方法是什么
不建议您测试保存到中的内容
数据库是正确的。它更多的是集成测试,而不是单元测试
测试,它超出了类的范围
可能有很多原因导致数据无法正确保存在数据库中,但您的类的行为是正常的,例如网络问题,但如果UT失败则不正确
相反,您应该测试您的类,以了解在数据库插入失败或发生异常时类的行为。然后使用您的模拟框架以这些期望来模拟存储库,并在类的测试中相应地断言
一些好的阅读资料和您不应该测试正在实施单元测试的类中使用的另一个模块/类的逻辑 您应该只测试/验证对该模块的调用是否正在被调用,就像您的业务逻辑所说的那样。您应该只关注该类的业务逻辑,只针对您正在编写的单元测试用例 在您的案例中,IGroupRepository是另一个模块/类,而不是为其编写单元测试的模块/类。相反,如果您想验证是否保存了数据,那么您应该在为IGroupRepository实现的另一个测试用例中包含该数据
但是,不建议编写用于数据保存的单元测试,并将其视为集成测试的一部分。是的,您正确地认为编写测试的方式有问题。事实上,您并不是在测试
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);
}
在您使用的模拟框架中应该有类似的东西