测试CRUD类。

时间:2014-08-19 12:45:40

标签: c# visual-studio unit-testing crud

我有一些问题。我在我的项目中写了一些单元测试,但我不知道如何测试我的CRUD方法..也许它们不可测试; /

这是我的方法之一:

    public static void IncrementInvalidLoginColumn(string login)
    {
        User user;

        using (DTContext context = new DTContext())
        {
            try
            {
                user = context.Users.Where(u => u.Login.CompareTo(login) == 0).FirstOrDefault();

                if (user.InvalidLogins < 3)
                {
                    user.InvalidLogins = user.InvalidLogins + 1;
                }

                context.SaveChanges();
            }
            catch
            {

            }        
        }            
    }

也许有人会知道我该怎么做。

5 个答案:

答案 0 :(得分:3)

这取决于“单位”测试的含义。如果您不希望您的测试访问数据库,那么您的方法是不可测试的(或者至少没有重构)。

如果点击数据库是可以接受的(实际上是集成测试),那么你绝对可以测试你的方法。

以下是一些步骤: 1.安排初始数据。您可以在测试中直接使用DTContext的实例将系统置于预定义状态(基本上您在数据库中编写一些用户记录)

  1. 您运行要测试的方法(实际上使用自己的DTContext实例)

  2. 您再次使用DTContext直接从数据库中读取用户信息,并断言InvalidLogins属性已增加。

  3. 您需要确保删除手动输入的任何数据。


  4. 这是DI的要点:

    public class Example { 
      private IDatabaseGateway myDatabase; 
    
      public Example(IDatabaseGateway myDb) { 
        myDatabase = myDb;
      } 
    
      public void DoStuff() { 
        ... 
        myDatabase.GetData(); 
        ... 
      } 
    }
    

    您可以通过构造函数为您的业务类提供数据库的抽象,即您在需要它们的类中注入您的依赖项。

    准备好之后,在生产代码中,您将构造函数传递给IDatabaseGateway的具体实例,该实例将转到实际数据库。

    在单元测试的情况下,您传递相同接口的模拟实例。模拟是一个特殊的对象,您可以设置/配置以返回您想要的内容。存在各种用于模拟的库(一个简单的库是Moq)。

    但是,如果不对代码进行过多修改,最好坚持使用可以访问数据库的集成测试。它将为您提供简单有效的测试。 特别是因为在EF中模拟DbContext存在一些缺陷(例如,当你在生产中使用它们时,某些查询可能不起作用,使用模拟测试EF中的更新有点棘手)。

答案 1 :(得分:2)

好的,所以我读了你所有的帖子,他们非常有帮助。 我使用MOQ框架,这是我如何做的例子。

这就是Liviu M.告诉我的例子:

 public class CRUDclass
 {
    private DTContext _context;

    public CRUDclass(DTContext myObj)
    {
        _context = myObj;
    }
 }

我们有CRUD类,它们直接在我们的数据库上进行操作。我们有一个带有一个参数和私有字段的构造函数。我们的背景是:)

这是(例如)我在CRUDclass中的方法:

public bool AddUser(User user)
{
  try
   {
     _context.Users.Add(user);
     _context.SaveChanges();

     return true;
   }
   catch
   {
     return false;
    }  
 }

Ovecourse他有我们的DTContext类巫婆DBSet因为我使用实体框架。之后,我能够编写一些测试方法:

[TestMethod]
    public void Should_Add_User()
    {
        var mockSet = new Mock<DbSet<User>>();
        var mockContext = new Mock<DTContext>();

        mockContext.Setup(m => m.Users).Returns(mockSet.Object);

        var usrCRUD = new UserCRUD(mockContext.Object);

        var usr = new User();
        usr.Login = "Login_Name";
        usr.Email = "loginName@test.com";
        usr.Password = "***";
        usr.InvalidLogins = 0;
        usr.RememberID = 0;

        usrCRUD.AddUser(usr);         

        mockSet.Verify(m => m.Add(It.Is<User>(arg => arg.Login == "Login_Name")));            
        mockContext.Verify(m => m.SaveChanges(), Times.Once());
    }

首先必须设置我的假对象(Mock&gt;)。 此测试方法检查我们的用户是否已添加到Mock :)

我希望它可以帮助某人,如果有什么不清楚请写一个问题:)

答案 2 :(得分:1)

单元测试的想法是测试你的ifs,交换机等,而不是数据库操作。 在您的情况下,您需要一个接口,它是DTContext的一个示例。在最简单的情况下,它可能如下所示。

public interface IObjectContext : IDisposable
{
    IEnumerable<User> Users { get; }
}

在更复杂的情况下,您可能需要使用IQueryable<T>IObjectSet<T>代替IEnumerable<T>

添加DTContext的部分类声明并使其实现IObjectContext。将构造函数添加到包含方法IncrementInvalidLoginColumn的类,其参数类型为IObjectContext。现在,您可以注入IObjectContext的任何实例,而不是在您的类中创建它。此实例可以是DTContext或模拟测试。您的课程已准备就绪,无需连接到真实数据库即可进行测试。

NB。如果是IDisposable的实例,最好注入Func<IObjectContext>而不是IObjectContext。然后,您可以为每个操作创建一个实例,并在之后立即处理它。

答案 3 :(得分:1)

如果代码中有CRUD操作,那么我建议使用MOQ框架进行单元测试。以下链接非常有用:

Quick Start

Code Project

答案 4 :(得分:1)

理想情况下,每次调用方法时,您都会注入DTContext而不是创建新的private readonly IDTContext _context; public CrudClass(IDTContext context) { _context = context } 。这样你就可以在单元测试中模拟该对象,并验证它是否按预期调用。

您的构造函数看起来像:

public static void IncrementInvalidLoginColumn(string login)
{
    User user;

    try
    {
        user = _context.Users.Where(u => u.Login.CompareTo(login) == 0).FirstOrDefault();

        if (user.InvalidLogins < 3)
        {
            user.InvalidLogins = user.InvalidLogins + 1;
        }

        _context.SaveChanges();
    }
    catch
    {
    // Handle errors
    }        
}

您的方法现在看起来像

IDTContext

然后在您的测试中,如果您使用的是像Moq这样的框架,您基本上会编写该对象的行为方式并对其进行测试。例如,设置模拟Users以始终为您的SaveChanges()集合和{{1}}方法返回相同的用户,会将无效登录的数量写入您可以测试的变量。