在 Dapper 中模拟匿名类型参数并按参数属性筛选结果



我不是很熟悉Moq和NUnit,这就是为什么我在这个问题上挣扎。我使用Dapper作为我的通用存储库,它被注入到一个服务中,然后用于实现逻辑。我的问题是,我在LinQ的选择中使用它,从前一个对象传递参数。我不知道如何在模拟中反映这一点…

这是我的服务:

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;
}
[...]
}
}

正如您所看到的,检索UserEmail和RoleName的调用是由前面的"_dataRepository.GetEntitiesAsync"这是什么我不知道如何嘲笑…

这是我的通用/匿名库:

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();
}
}
[...]

这是我的测试类:

[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();
}
}

这是我的"mocked"数据构造函数:

public static class MockedDAOs
{
public static IEnumerable<UserDAO> GetMockedUsers()
{
List<UserDAO> users = new List<UserDAO>();
users.Add(new UserDAO()
{
Id = 1,
Email = "lordvaderr@galacticempire.com",
Address = "Alderaan Sector 1234",
LanguajePreference = "English",
UpdateUser = "Admin"
});
users.Add(new UserDAO()
{
Id = 2,
Email = "senatorpalpatine@galacticempire.com",
Address = "Alderaan Sector 1233",
LanguajePreference = "English",
UpdateUser = "Admin"
});
users.Add(new UserDAO()
{
Id = 3,
Email = "generalrommohc@galacticempire.com",
Address = "Alderaan Sector 1232",
LanguajePreference = "English",
UpdateUser = "Admin"
});
users.Add(new UserDAO()
{
Id = 4,
Email = "secenthsister@galacticempire.com",
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 = "lordvaderr@galacticempire.com",
RoleName = "General Director"
});
participatorsResponse.Add(new ParticipatorsResponse()
{
UserEmail = "senatorpalpatine@galacticempire.com",
RoleName = "CEO"
});
participatorsResponse.Add(new ParticipatorsResponse()
{
UserEmail = "generalrommohc@galacticempire.com",
RoleName = "Strategy Director"
});
participatorsResponse.Add(new ParticipatorsResponse()
{
UserEmail = "secenthsister@galacticempire.com",
RoleName = "Deliver"
});
List<StudyReponse> studyResponse = new List<StudyReponse>();
studyResponse.Add(new StudyReponse()
{
StudyCode = "order66",
Participators = participatorsResponse
});
return new StudiesResponse()
{
Studies = studyResponse
};
}
}

我没有主意了,我找不到任何这样的场景的例子…

编辑:好的,我发现了一个帖子,我认为可以使用:

测试:

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

但是它不起作用。使用这段代码,第一次调用恢复IEnumerable返回0结果…我会继续找的。如有任何帮助,不胜感激。

我设法解决了这个问题。测试的正确代码是:

[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); 
}
如你所见,我用的是KellermanSoftware。CompareNetObjects来做断言,这就是为什么我必须修改测试方法,从LinQ WhereSelect响应解析参与者到列表,这样比较器就不会看到与我构造的预期响应的差异。

方法代码略有不同:

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

最新更新