Home > Enterprise >  Mocking an Anonymous type parameter in Dapper and Filtering result by parameter's property
Mocking an Anonymous type parameter in Dapper and Filtering result by parameter's property

Time:06-18

I'm not very familiar with Moq and NUnit, that's why I'm struggling with this one. I'm using Dapper for my generic repository, and it's been injected into a service and, then, used to fulfil the logic. My problem is that I use it in a LinQ's Select passing a parameter from the previous Object. And I have no idea how to reflect that in the Mock...

This is my Service:

public class StudyService: IStudyService
    {
        private readonly ILogger<StudyService> _logger;
        private readonly IDataRepository _dataRepository;

        public StudyService(ILogger<StudyService> logger, IDataRepository dataRepository)
        {
            _logger = logger;
            _dataRepository = dataRepository;
        }
[...]
        // This is the method to test:
        public async Task<StudiesResponse> GetAllStudies()
        {
            StudiesResponse studies = new StudiesResponse();
            List<StudyReponse> list = new List<StudyReponse>();

            foreach (StudyDAO study in await _dataRepository.GetEntitiesAsync<StudyDAO>())
            {
                StudyReponse resp = new StudyReponse()
                {
                    StudyCode = study.StudyCode,
                    Participators = _dataRepository.GetEntitiesAsync<RoleUserDAO>(new { @StudyId = study.Id }).Result.Select(x => new ParticipatorsResponse()
                    {
                        UserEmail = _dataRepository.GetEntityAsync<UserDAO>(new { @Id = x.Id }).Result.Email,
                        RoleName = _dataRepository.GetEntityAsync<RoleDAO>(new { @Id = x.Id }).Result.Name
                    })
                };


                list.Add(resp);
            }

            studies.Studies = list;
            return studies;
        }
[...]
   }
}

As you can see the calls to retrieve UserEmail and RoleName are fed by the Select of the previous "_dataRepository.GetEntitiesAsync" This is what I don't have a clue how to mock...

This is my generic/anonymous repository:

   public class DataRepository : IDataRepository
    {
        private readonly IConfiguration _configuration;
       
        public DataRepository(IConfiguration configuration)
        {
            _configuration = configuration;
        }

        public async Task<IEnumerable<T>> GetEntitiesAsync<T>()
        {
            using(IDbConnection conn = new SqlConnection(_configuration.GetConnectionString("SqlConnection")))
            {
                return await conn.GetListAsync<T>();
            }   
        }
        public async Task<IEnumerable<T>> GetEntitiesAsync<T>(object query)
        {
            using (IDbConnection conn = new SqlConnection(_configuration.GetConnectionString("SqlConnection")))
            {
                return await conn.GetListAsync<T>(query);
            }
        }

        public async Task<T> GetEntityAsync<T>(object query)
        {
            using (IDbConnection conn = new SqlConnection(_configuration.GetConnectionString("SqlConnection")))
            {
                IEnumerable<T> result = await conn.GetListAsync<T>(query);
                return result.FirstOrDefault();
            }
        }
[...]

This is my test class:

[TestFixture]
    public class Tests
    {
        IEnumerable<StudyDAO> _studies;
        IEnumerable<UserDAO> _users;
        IEnumerable<RoleDAO> _roles;
        IEnumerable<RoleUserDAO> _roleUsers;

        
        [SetUp]
        public void Setup()
        {
            _studies = MockedDAOs.GetMockedStudies();
            _users = MockedDAOs.GetMockedUsers();
            _roles = MockedDAOs.GetMockedRoles();
            _roleUsers = MockedDAOs.GetMockedRoleUsers();
        }

        [Test]
        public void GetAllStudiesTest()
        {
            var _data = new Mock<IDataRepository>();
            _data.Setup(m => m.GetEntitiesAsync<StudyDAO>()).Returns(Task.FromResult(_studies));
            _data.Setup(m => m.GetEntitiesAsync<RoleUserDAO>(It.IsAny<Object>())).Returns(Task.FromResult(_roleUsers));
            _data.Setup(m => m.GetEntityAsync<UserDAO>(It.IsAny<Object>())).Returns(Task.FromResult(_users.Where(u => u.Id ==????)));
            _data.Setup(m => m.GetEntityAsync<RoleDAO>(It.IsAny<Object>())).Returns(Task.FromResult(_roles.Where(u => u.Id ==????)));

            var _logger = Mock.Of<ILogger<StudyService>>();
            StudyService _service = new StudyService(_logger, _data.Object);

            var result = _service.GetAllStudies();

            Assert.Pass();
        }
    }

And this is my "mocked" data constructors:

 public static class MockedDAOs
    {
        public static IEnumerable<UserDAO> GetMockedUsers()
        {
            List<UserDAO> users = new List<UserDAO>();
            users.Add(new UserDAO()
            {
                Id = 1,
                Email = "[email protected]",
                Address = "Alderaan Sector 1234",
                LanguajePreference = "English",
                UpdateUser = "Admin"
            });
            users.Add(new UserDAO()
            {
                Id = 2,
                Email = "[email protected]",
                Address = "Alderaan Sector 1233",
                LanguajePreference = "English",
                UpdateUser = "Admin"
            });
            users.Add(new UserDAO()
            {
                Id = 3,
                Email = "[email protected]",
                Address = "Alderaan Sector 1232",
                LanguajePreference = "English",
                UpdateUser = "Admin"
            });
            users.Add(new UserDAO()
            {
                Id = 4,
                Email = "[email protected]",
                Address = "Alderaan Sector 1231",
                LanguajePreference = "English",
                UpdateUser = "Admin"
            });
            return users;
        }

        public static IEnumerable<StudyDAO> GetMockedStudies()
        {
            List<StudyDAO> studies = new List<StudyDAO>();
            studies.Add(new StudyDAO()
            {
                Id = 1,
                StudyCode = "order66",
                Company = "Galactic Empire",
                UpdateUser = "Admin"
            });

            return studies;
        }

        public static IEnumerable<RoleDAO> GetMockedRoles()
        {
            List<RoleDAO> roles = new List<RoleDAO>();
            roles.Add(new RoleDAO()
            {
                Id = 1,
                Name = "General Director",
                Curriculum = "Ruthless Management I",
                UpdateUser = "Admin"
            });
            roles.Add(new RoleDAO()
            {
                Id = 2,
                Name = "CEO",
                Curriculum = "Smoke and Mirrors I",
                UpdateUser = "Admin"
            });
            roles.Add(new RoleDAO()
            {
                Id = 3,
                Name = "Strategy Director",
                Curriculum = "Detecting Critical Targets",
                UpdateUser = "Admin"
            });
            roles.Add(new RoleDAO()
            {
                Id = 4,
                Name = "Deliver",
                Curriculum = "Silent Aproaches",
                UpdateUser = "Admin"
            });
            return roles;
        }

        public static IEnumerable<RoleUserDAO> GetMockedRoleUsers()
        {
            List<RoleUserDAO> roleUsers = new List<RoleUserDAO>();
            roleUsers.Add(new RoleUserDAO()
            {
                Id = 1,
                UserId = 1,
                RoleId = 1,
                StudyId = 1,
                UpdateUser = "Admin"
            });
            roleUsers.Add(new RoleUserDAO()
            {
                Id = 2,
                UserId = 2,
                RoleId = 2,
                StudyId = 1,
                UpdateUser = "Admin"
            });
            roleUsers.Add(new RoleUserDAO()
            {
                Id = 3,
                UserId = 3,
                RoleId = 3,
                StudyId = 1,
                UpdateUser = "Admin"
            });
            roleUsers.Add(new RoleUserDAO()
            {
                Id = 4,
                UserId = 4,
                RoleId = 4,
                StudyId = 1,
                UpdateUser = "Admin"
            });
            return roleUsers;
        }

        public static StudiesResponse GetMockedStudiesResponse()
        {
            List<ParticipatorsResponse> participatorsResponse = new List<ParticipatorsResponse>();
            participatorsResponse.Add(new ParticipatorsResponse(){
                UserEmail = "[email protected]",
                RoleName = "General Director"
            });
            participatorsResponse.Add(new ParticipatorsResponse()
            {
                UserEmail = "[email protected]",
                RoleName = "CEO"
            });
            participatorsResponse.Add(new ParticipatorsResponse()
            {
                UserEmail = "[email protected]",
                RoleName = "Strategy Director"
            });
            participatorsResponse.Add(new ParticipatorsResponse()
            {
                UserEmail = "[email protected]",
                RoleName = "Deliver"
            });

            List<StudyReponse> studyResponse = new List<StudyReponse>();
            studyResponse.Add(new StudyReponse()
            {
                StudyCode = "order66",
                Participators = participatorsResponse
            });

            return new StudiesResponse()
            {
                Studies = studyResponse
            };
        }
    }

I'm out of ideas and I can't find any example with a scenario like this...

EDIT: Ok, I found a post with something that I thought can be used:

Test:

        [Test]
        public void GetAllStudiesTest()
        {
            var _data = new Mock<IDataRepository>();
            _data.Setup(m => m.GetEntitiesAsync<StudyDAO>()).Returns(Task.FromResult(_studies));
            _data.Setup(m => m.GetEntitiesAsync<RoleUserDAO>(It.IsAny<Object>())).ReturnsAsync((Object obj) => _roleUsers.Where(x => x.Id == obj.Id));
            _data.Setup(m => m.GetEntityAsync<UserDAO>(It.IsAny<Object>())).ReturnsAsync((Object obj) => _users.Where(x => x.Id == obj.Id).FirstOrDefault());
            _data.Setup(m => m.GetEntityAsync<RoleDAO>(It.IsAny<Object>())).ReturnsAsync((Object obj) => _roles.Where(x => x.Id == obj.Id).FirstOrDefault());

            var _logger = Mock.Of<ILogger<StudyService>>();
            StudyService _service = new StudyService(_logger, _data.Object);

            var result = _service.GetAllStudies();

            Assert.True(comparator.Compare(result, MockedDAOs.GetMockedStudiesResponse()).AreEqual); 
        }

But it's not working. With this code, the first call to recover the IEnumerable returns 0 results... I'll keep looking. Any help will be appreciated.

CodePudding user response:

I managed to solve the issue. The correct code for the Test is:

        [Test]
        public void GetAllStudiesTest()
        {
            var _data = new Mock<IDataRepository>();
            _data.Setup(m => m.GetEntitiesAsync<StudyDAO>()).Returns(Task.FromResult(_studies));
            _data.Setup(m => m.GetEntitiesAsync<RoleUserDAO>(It.IsAny<Object>())).ReturnsAsync((Object obj) => _roleUsers.Where(x => x.StudyId == (int)obj.GetType().GetProperty("StudyId").GetValue(obj, null)));
            _data.Setup(m => m.GetEntityAsync<UserDAO>(It.IsAny<Object>())).ReturnsAsync((Object obj) => _users.Where(x => x.Id == (int)obj.GetType().GetProperty("Id").GetValue(obj, null)).FirstOrDefault());
            _data.Setup(m => m.GetEntityAsync<RoleDAO>(It.IsAny<Object>())).ReturnsAsync((Object obj) => _roles.Where(x => x.Id == (int)obj.GetType().GetProperty("Id").GetValue(obj, null)).FirstOrDefault());

            var _logger = Mock.Of<ILogger<StudyService>>();
            StudyService _service = new StudyService(_logger, _data.Object);

            StudiesResponse result = _service.GetAllStudies().Result;
            StudiesResponse expectedResult = MockedDAOs.GetMockedStudiesResponse();

            var comparation = comparator.Compare(result, expectedResult);

            Assert.True(comparation.AreEqual); 
        }

As you can see I'm using KellermanSoftware.CompareNetObjects to do the assertion, that's why I had to modify the method to test, parsing the Participators from a LinQ WhereSelect response to a List, so the comparator would not see a difference with my constructed expected response.

This is the slightly different method code:

        public async Task<StudiesResponse> GetAllStudies()
        {
            StudiesResponse studies = new StudiesResponse();
            List<StudyReponse> list = new List<StudyReponse>();
            foreach (StudyDAO study in await _dataRepository.GetEntitiesAsync<StudyDAO>())
            {
                StudyReponse resp = new StudyReponse()
                {
                    StudyCode = study.StudyCode,
                    Participators = _dataRepository.GetEntitiesAsync<RoleUserDAO>(new { @StudyId = study.Id }).Result.Select(x => new ParticipatorsResponse()
                    {
                        UserEmail = _dataRepository.GetEntityAsync<UserDAO>(new { @Id = x.Id }).Result.Email,
                        RoleName = _dataRepository.GetEntityAsync<RoleDAO>(new { @Id = x.Id }).Result.Name
                    }).ToList()
                };
                list.Add(resp);
            }
            studies.Studies = list;
            return studies;
        }
  • Related