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