How to test [TDD] if an specific entry already exists in database

时间:2019-01-18 18:39:00

标签: c# database unit-testing mocking tdd

I'm new to C# and learning about TDD. I see the use of mock objects, but I'm stuck for days searching for something like what I'm doing, and I didn't found anything.

My first rule to unit test is that should not exists two specific objects with the same property.

I'll give you an example: let's say that the object is student and I can't have two leaders, so, in my newbie mind, my test is something like create two students and set them as leaders. When I persist the secont i'll take an exception, or something like this.

Well, TDD is about not having a data project yet, and mocks are just for emulate a single entity (if I understood the concept correctly)... so... how to emulate a database so I can check if there`s a leader before persist, or even create the student or set the student as leader. Or there's a better way to do this?

Many thanks!!!

2 个答案:

答案 0 :(得分:2)

You need to mock everything including your database layer. If you access your database through IRepository instance then you should create something like this:

 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;
     }
 }

Upper layer can be responsible for throwing exception in case a student already has a teacher and there is an attempt for adding the second one.

答案 1 :(得分:2)

Personally, I would not be testing a database implementation. I would set up the database to make sure the column is set as unique and let the database do its work.

That being said, if you want to test that you're catching your uniqueness in the database abstraction. You would setup an interface implementation with multiple items two of which being non-unique and make sure you catch it.

e.g

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
     }
}