-1

I have a repository

public class StudentsPersonalDetailsRepository : IStudentPersonalDetailsRepository
{
    private readonly StudentManagementSystemEntities _studentsDbContext;
    private readonly ILogger _logger;
    public StudentsPersonalDetailsRepository(StudentManagementSystemEntities context, ILogger<IStudentPersonalDetailsRepository> logger)
    {
        _studentsDbContext = context;
        _logger = logger;
    }
    public IQueryable<StudentPersonalDetails> StudentPersonalDetails => _studentsDbContext.StudentPersonalDetails;
    ......
}

In my Service layer, I am having a service as

public class StudentsPersonalDetailsService:IStudentPersonalDetailsService
{
    private readonly IStudentPersonalDetailsRepository _repository;
    private readonly ILogger _logger;
    public StudentsPersonalDetailsService(IStudentPersonalDetailsRepository studentPersonalDetailsRepository,ILogger<StudentsPersonalDetailsService> logger)
    {
        _repository = studentPersonalDetailsRepository;
        _logger = logger;
    }
    ......
    ......
    public StudentModelResponse GetStudentById(int id)
    {
        Domain.Entities.StudentPersonalDetails obj = _repository.StudentPersonalDetails.
                                                    Where(i => i.RollNo == id)
                                                    .Select(i=>new Domain.Entities.StudentPersonalDetails {
                                                        RollNo=i.RollNo,
                                                        FirstName=i.FirstName,
                                                        LastName=i.LastName,
                                                        MailId=i.MailId,
                                                        MiddleName=i.MiddleName,
                                                        DateOfBirth=i.DateOfBirth,
                                                        GenderOfPerson=i.GenderOfPerson
                                                    }).FirstOrDefault();
        StudentModel ob = StudentModel.Translator(obj);
        return new StudentModelResponse { StudentModel=ob};
    }
}

My Test code is

namespace StudentUnitTests
{
     public class StudentServiceShould
     {
         [Theory]
         [InlineData(1)]
         public void AbleToRetrieveStudentById(int n)
         {
             var mock = new Mock<IStudentPersonalDetailsRepository>();
             var logger = new Mock<ILogger<StudentsPersonalDetailsService>> ();
             var ob = new StudentsPersonalDetailsService(mock.Object, logger.Object);
         }
     }
}

I need to write a unit test for GetStudentById() and check the values returned by the function.

Please help me to how to mock the service layer.

  • Try something first and If you get stuck provide a [mcve] that can be used to reproduce the problem. – Nkosi Jul 10 '17 at 13:19
  • I have already tried the piece of code edited in the question. I am new to Mocking, so facing issues to setup the mock. Please help me out. – Murali Krishna Jul 10 '17 at 13:31

1 Answers1

0

In the above we have two things happening within StudentsPersonalDetailsService.GetStudentById()

  1. Retrieve the student info from the repository.
  2. Create a student model from the data retrieved from the repository

Note: Something looks strange when reading from the repository. If the items in the repository are StudentPersonalDetails why create new instances

We can stub retrieving the student data like so

 public class StudentServiceShould
 {
     [Theory]
     [InlineData(1)]
     public void AbleToRetrieveStudentById(int n)
     {
        var students = new []{
          // new Domain.Entities.StudentPersonalDetails for student role 1,
          // new Domain.Entities.StudentPersonalDetails for student role 2,
          // new Domain.Entities.StudentPersonalDetails for student role 3
        };         


         var mock = new Mock<IStudentPersonalDetailsRepository>();
         mock.SetupGet(mk => mk.StudentPersonalDetails).Returns(students.AsQueryable());
         var logger = new Mock<ILogger<StudentsPersonalDetailsService>> ();
         var ob = new StudentsPersonalDetailsService(mock.Object, logger.Object);
     }
 }

Creating the StudentModel objects is encapsulated in the Translator but because it is a static method on the 'StudentModel' we cannot mock it and will have to test the reading and conversion in one go.

AlanT
  • 3,627
  • 20
  • 28
  • I couldn't get it. If I have 1000 records, do I need to enter all the data into var students list? Please explain me why do we use mock.Setup and how to set Returns. – Murali Krishna Jul 12 '17 at 09:04
  • What, in your mind, is the goal for unit testing? In the above code we are testing that if we pass an Id number into `StudentsPersonalDetailsService.GetStudentById()`, the code will read the appropriate record from the repository and return a `StudentModelResponse` created from the data returned from the repository. That is all we are testing. The mock repository allows us do this without having to use the real repository. We only need the mock to be capable of returning a few different records to show that this `StudentsPersonalDetailsService.GetStudentById()` is working correctly – AlanT Jul 12 '17 at 09:24
  • Ok I got the concept. Thanks for making it very clear. If I really retrieve it from database, then it would become integration testing. Moreover, we are isolating the service layer and we are just testing its behavior. It's really very clear. Thanks a lot! – Murali Krishna Jul 12 '17 at 09:40