如果数据库中已存在特定条目,如何测试 [TDD]
How to test [TDD] if an specific entry already exists in database
我是 C# 的新手,正在学习 TDD。我看到了模拟对象的使用,但几天来我一直在寻找类似我正在做的事情,但我没有找到任何东西。
我对单元测试的第一条规则是不应该存在两个具有相同 属性.
的特定对象
我给你举个例子:假设对象是学生,我不能有两个领导者,所以,在我的新手心目中,我的测试就像创建两个学生并将他们设置为领导者。当我坚持第二个时,我会采取例外,或类似的方式。
好吧,TDD 还没有数据项目,模拟只是为了模拟单个实体(如果我理解正确的话)...所以...如何模拟数据库以便我可以检查如果坚持之前有leader,甚至创建学生或将学生设置为leader。或者有更好的方法吗?
非常感谢!!!
您需要模拟所有内容,包括您的数据库层。如果您通过 IRepository
实例访问您的数据库,那么您应该创建如下内容:
public interface IRepository
{
List<Student> GetAllStudents();
void AddStudent(Student student);
Teacher GetStudentTeacher(int studentId);
}
public class MockRepository : IRepository
{
public static List<Student> Students { get; set; }
public static List<Teachers> Teachers { get; set; }
static MockRepository()
{
Students = new List<Student>();
}
public List<Student> GetAllStudents()
{
return Students.ToList();
}
public void AddStudent(Student student)
{
Students.Add(student);
}
public Teacher GetStudentTeacher(int studentId)
{
var student = Students.FirstOrDefault(s => s.Id == studentId);
if (student != null)
{
return Teachers.FirstOrDefault(t => t.Id == student.TeacherId);
}
return null;
}
}
如果学生已经有老师并且尝试添加第二个老师,上层可以负责抛出异常。
就个人而言,我不会测试数据库实现。我会设置数据库以确保将列设置为唯一并让数据库完成它的工作。
也就是说,如果您想测试您是否在数据库抽象中捕捉到您的独特性。您将设置一个包含多个项目的接口实现,其中两个项目是非唯一的,并确保您抓住它。
例如
public interface IPersonRepository
{
void AddPerson(Person person);
IEnumerable<Person> GetPeople();
}
public class PersonService
{
private static readonly IPersonRepository _repo;
public PersonService(IPersonRepository repo)
{
_repo = repo;
}
public void AddPerson(Person person)
{
var people = _repo.GetPeople();
if(people.Select(p=>p.LastName).Contains(person.LastName))
{
// person exists
}
_repo.AddPerson(person);
}
}
public class PersonServiceTests
{
public void ShouldNotAddPersonIfExists()
{
var mockRepo = new Mock<IPersonRepository>();
mockRepo.Set(r => r.GetPeople()).Returns(new[]{new Person(firstName, lastName), new Person(otherName, lastName));
var service = new PersonService(mockRepo.Object);
/// try add and check assertions or exceptions thrown
}
}
我是 C# 的新手,正在学习 TDD。我看到了模拟对象的使用,但几天来我一直在寻找类似我正在做的事情,但我没有找到任何东西。
我对单元测试的第一条规则是不应该存在两个具有相同 属性.
的特定对象我给你举个例子:假设对象是学生,我不能有两个领导者,所以,在我的新手心目中,我的测试就像创建两个学生并将他们设置为领导者。当我坚持第二个时,我会采取例外,或类似的方式。
好吧,TDD 还没有数据项目,模拟只是为了模拟单个实体(如果我理解正确的话)...所以...如何模拟数据库以便我可以检查如果坚持之前有leader,甚至创建学生或将学生设置为leader。或者有更好的方法吗?
非常感谢!!!
您需要模拟所有内容,包括您的数据库层。如果您通过 IRepository
实例访问您的数据库,那么您应该创建如下内容:
public interface IRepository
{
List<Student> GetAllStudents();
void AddStudent(Student student);
Teacher GetStudentTeacher(int studentId);
}
public class MockRepository : IRepository
{
public static List<Student> Students { get; set; }
public static List<Teachers> Teachers { get; set; }
static MockRepository()
{
Students = new List<Student>();
}
public List<Student> GetAllStudents()
{
return Students.ToList();
}
public void AddStudent(Student student)
{
Students.Add(student);
}
public Teacher GetStudentTeacher(int studentId)
{
var student = Students.FirstOrDefault(s => s.Id == studentId);
if (student != null)
{
return Teachers.FirstOrDefault(t => t.Id == student.TeacherId);
}
return null;
}
}
如果学生已经有老师并且尝试添加第二个老师,上层可以负责抛出异常。
就个人而言,我不会测试数据库实现。我会设置数据库以确保将列设置为唯一并让数据库完成它的工作。
也就是说,如果您想测试您是否在数据库抽象中捕捉到您的独特性。您将设置一个包含多个项目的接口实现,其中两个项目是非唯一的,并确保您抓住它。
例如
public interface IPersonRepository
{
void AddPerson(Person person);
IEnumerable<Person> GetPeople();
}
public class PersonService
{
private static readonly IPersonRepository _repo;
public PersonService(IPersonRepository repo)
{
_repo = repo;
}
public void AddPerson(Person person)
{
var people = _repo.GetPeople();
if(people.Select(p=>p.LastName).Contains(person.LastName))
{
// person exists
}
_repo.AddPerson(person);
}
}
public class PersonServiceTests
{
public void ShouldNotAddPersonIfExists()
{
var mockRepo = new Mock<IPersonRepository>();
mockRepo.Set(r => r.GetPeople()).Returns(new[]{new Person(firstName, lastName), new Person(otherName, lastName));
var service = new PersonService(mockRepo.Object);
/// try add and check assertions or exceptions thrown
}
}