C# Dapper:单元测试SQL查询
我从整洁的微型ORM开始,我使用整洁的彩虹。我想测试查询和它们检索到的数据 我的意思是,例如,我使用方法GetAll()的UserService,我想测试sql查询是否从某个列表中检索所有用户(不是从数据库中,因为我希望测试速度快)。你知道我怎么做吗 我的服务类(以及我要测试的方法):C# Dapper:单元测试SQL查询,c#,.net,unit-testing,tdd,dapper,C#,.net,Unit Testing,Tdd,Dapper,我从整洁的微型ORM开始,我使用整洁的彩虹。我想测试查询和它们检索到的数据 我的意思是,例如,我使用方法GetAll()的UserService,我想测试sql查询是否从某个列表中检索所有用户(不是从数据库中,因为我希望测试速度快)。你知道我怎么做吗 我的服务类(以及我要测试的方法): 公共静态类用户服务{ 公共静态IEnumerable GetAll(){ 返回DB.Users.All(); } } 关于单元测试查询和数据检索,您有什么建议吗 谢谢我建议大家阅读一下依赖注入和存储库模式。如果
公共静态类用户服务{
公共静态IEnumerable GetAll(){
返回DB.Users.All();
}
}
关于单元测试查询和数据检索,您有什么建议吗
谢谢我建议大家阅读一下依赖注入和存储库模式。如果采用上面代码中的方法,您将很难模拟出依赖项,因为类和方法是静态的 这里有一个更好的方法
public interface IUserRepository
{
IEnumerable<User> GetAll()
}
public class UserRepository : IUserRepository
{
public IEnumerable<User> GetAll()
{
return DB.Users.All();
}
}
public class UserService
{
IUserRepository _userRepository;
public UserService(IUserRepository userRepository)
{
_userRepository = userRepository
}
public Enumerable<User> GetAll(){
return _userRepository.GetAll();
}
}
这个例子有点做作,因为测试您是否可以从一个虚假的存储库中获取数据实际上没有意义。在现实中,如果你的服务中有一些业务逻辑,比如说找回了一个用户,然后检查他们是否超过了某个年龄或其他什么。e、 g.UserService上的IsLegalDrivingAge方法。使用Dapper,您的SQL很可能是字符串文本,可能与C#条件混合,语法未验证,DB引用可能错误。你的测试本能很好。但是,对真实数据库运行代码是判断它是否输出有效查询的唯一方法。所以这里需要的测试是集成测试。这并不难,您可以使用单元测试框架来完成,但由于测试必须命中真实的数据库,因此您可能不希望在运行单元测试的任何地方都运行它,例如在构建服务器上 然后,因为Dapper是ADO的扩展方法,所以要对使用查询的代码进行单元测试,需要将其包装在存储库模式中。似乎是这里的工具
如果这一切看起来不必要的困难,请尝试(免责声明:我写的)。您在一个真正的SQL窗口中编写SQL,该窗口连接到数据库,SQL在键入时经过验证。每次保存文件时,您的查询都会针对数据库进行集成测试,而无需举手。然后,如果查询运行,QueryFirst将生成包装器代码以供您使用,其中包括一个接口,以便您可以在对使用代码进行单元测试时轻松模拟真实查询。这是向前迈出的一步,不是吗?您需要模拟数据存储。什么是
DB
?模拟数据源。向它注入测试数据,看看它是否返回正确的数据。有很多模拟框架,Moq和RhinoMock浮现在脑海中。选一个开始吧!谢谢,这很有帮助。然而,我最需要的是测试sql查询,我的类的一些方法运行原始查询。是否有任何方法可以加载可通过查询检索的假数据?你知道我如何测试它吗?谢谢您可以在testsetup方法中启动事务,然后在teardown方法中回滚该事务。这意味着数据库保持一致状态。您应该有一个数据库副本,其中没有数据,以便进行测试。请创建一个测试包来加载数据。注意,这是一个集成测试,而不是单元测试。你也看过精巧的单元测试,它们可能会准确地告诉你你在寻找什么。从我这里得到+1。@Andrew我一直在试图解释这个这个例子有点做作,因为测试你是否可以从一个假的存储库中将数据取回给我的同事是没有意义的。我们有一个伪造的数据库,它不是一个很好的单位-ish@Andrew,赞成存储库模式,但我认为这不是OP所问的。好吧,至少我是如何得到它的,问题更多的是关于如何测试简洁的SQL查询本身,而不是对数据库进行实际查询,类似于下面的答案:。由于查询很可能包含一些逻辑(过滤/排序/聚合),因此以某种方式对其进行测试也是有意义的。
public interface IUserRepository
{
IEnumerable<User> GetAll()
}
public class UserRepository : IUserRepository
{
public IEnumerable<User> GetAll()
{
return DB.Users.All();
}
}
public class UserService
{
IUserRepository _userRepository;
public UserService(IUserRepository userRepository)
{
_userRepository = userRepository
}
public Enumerable<User> GetAll(){
return _userRepository.GetAll();
}
}
public class FakeUserRepository : IUserRepository
{
public IEnumerable<User> GetAll()
{
return new List<User> { new User {FirstName='Bob', LastName='Smith'}, };
}
}
[Test]
public void GetAll_ShouldReturnAllFromFake()
{
// Arrrange
var userService = new UserService(new FakeUserRepository())
// Act
var result = userService.GetAll();
// Assert
var user = result[0];
Assert.AreEqual("Bob", user.FirstName);
Assert.AreEqual("Smith", user.LastName);
}