C# 访问实体数据库的单元测试功能

C# 访问实体数据库的单元测试功能,c#,.net,winforms,entity-framework,C#,.net,Winforms,Entity Framework,尝试对访问实体框架的函数进行单元测试。所以我试着把所有的实体代码放到下面的测试函数中?然而,它在Linq语句处停止;显然,试图访问数据库对它来说太麻烦了。也许一个解决办法是在基于SQLLite或compact的单元测试函数中创建一个副本数据库;(无论如何,它不是一个大数据库)那么执行就不必离开测试功能了?这是否可能,我将如何实施 public void RetreiveKeyFnTest() { StegApp target = new StegApp(); // TOD

尝试对访问实体框架的函数进行单元测试。所以我试着把所有的实体代码放到下面的测试函数中?然而,它在Linq语句处停止;显然,试图访问数据库对它来说太麻烦了。也许一个解决办法是在基于SQLLite或compact的单元测试函数中创建一个副本数据库;(无论如何,它不是一个大数据库)那么执行就不必离开测试功能了?这是否可能,我将如何实施

public void RetreiveKeyFnTest()
    {
        StegApp target = new StegApp(); // TODO: Initialize to an appropriate value
        string username = "david"; // TODO: Initialize to an appropriate value
        string password = "david1"; // TODO: Initialize to an appropriate value
        string ConnectionString = ConfigurationManager.ConnectionStrings["DatabaseEntities"].ToString();
        var dataContext = new DatabaseEntities(ConnectionString);
        var user = dataContext.Users.FirstOrDefault(u => u.Username.Equals(username) && u.Password.Equals(password));
        Assert.IsNotNull(user);

        //target.RetreiveKeyFn(username, password);
        //Assert.IsInstanceOfType(target.RetreiveLogs,typeof(DataAccess));
        //Assert.IsInstanceOfType(target.p);
        //Assert.IsNotNull(target.RetreiveLogs.AuthenitcateCredentials(username,password));
        //Assert.Inconclusive("A method that does not return a value cannot be verified.");
    }
下面是我尝试测试的代码:

public void RetreiveKeyFn(string username, string password)
    {

        BusinessObjects.User p = RetreiveLogs.AuthenitcateCredentials(username,password);
        if (p != null)
        {
            if (RetreiveLogs.RetreiveMessages(p.UserId) == null)
            {
                DisplayLogs.Text = "Sorry No messages for you recorded in Database, your correspondant might have chose not to record the entry";
            }
            else
            {
                MessageBox.Show("LogId = " + RetreiveLogs.RetreiveMessages(p.UserId).LogId + "\n" +
                "UserId = " + RetreiveLogs.RetreiveMessages(p.UserId).UserId + "\n" +
                "Message Key = " + RetreiveLogs.RetreiveMessages(p.UserId).MessageKey + "\n" + "PictureId = " + RetreiveLogs.RetreiveMessages(p.UserId).PictureId +
                " Date & time = " + RetreiveLogs.RetreiveMessages(p.UserId).SentDateTime);
                DisplayLogs.Visible = true;
            }
        }
        else
        {
            MessageBox.Show("Please enter your correct username and password in order to retreive either key, image or both from Databse");
        }


    }

首先,您应该能够在测试应用程序中访问与主/实际应用程序中使用的数据库相同的数据库。您只需要确保您的测试项目在其自己的App.config中包含您的连接字符串

上下文的初始化应该在您的StegApp()内部进行,或者您应该能够从不同的作用域向您的StegApp()传递上下文。从我读到的代码来看,您的StegApp()将无法访问您创建的dataContext变量

您对null user的测试已经在AuthenticateCredentials()方法下的RetrieveKeyFn()中进行,因此不需要第一个“Assert.IsNotNull(user)”。我建议将RetrieveKeyFn的业务逻辑与UI行为分开,以便轻松地进行单元测试。您可以绑定“Messagebox”操作来表示一个按钮单击事件处理程序,它只调用RetrieveKeyFn()。我可能会建议如下:

public class StegApp
{

      public DatabaseEntities context;
      //other properties

      public StegApp()
      {
           //assuming your DatabaseEntities class inherits from DbContext. 
           //You should create other constructors that allow you to set options
           //like lazy loading and mappings
           this.context = new DatabaseEntities(); 
      } 

      //ASSUMING YOUR RetrieveLogs.RetrieveMessages() function returns 
      //a Message object. replace this type with whatever type the
      //RetrieveLogs.RetrieveMessages() method returns.
      public Message RetrieveKeyFn (string username, string password)
      {

          BusinessObjects.User p = RetreiveLogs.AuthenitcateCredentials(username,password);
          if (p != null)
          {
              var message = RetrieveLogs.RetrieveMessages(p.UserId);
              if (message == null)
                  // handle behavior for no messages. In this case 
                  // I will just create a new Message object with a -1 LogId
                  return new Message {LogId =-1};
              else
                  return message;
          }
          else
              //handle behavior when the user is not authenticated. 
              //In this case I throw an exception
              throw new Exception();

      }

     //on your button click handler, do something like:
     // try 
     // {
     //     var message = RetrieveKeyFn(txtUsername.Text.Trim(), txtPassword.Text.Trim());
     //     if (message.LogId == -1)
     //         DisplayLogs.Text = "Sorry No messages for you recorded in Database, your correspondant might have chose not to record the entry";
     //     else
     //     {
     //         MessageBox.Show("Log Id = " + message.LogId)
     //         etc. etc. etc.
     //     }
     // }
     // catch
     // {
     //       MessageBox.Show ("user is not authenticated");
     // }

}
进行单元测试时,请记住在测试项目的App.Config中包含适当的配置字符串如果App.Config尚不存在,请继续创建一个。您应该为所有可能性创建测试(即1)用户有效,您得到消息,2)用户有效,没有消息,3)用户无效)

下面是案例2的一个例子

    [TestMethod]
    public void RetrieveKeyFnTest1()
    {
        StegApp target = new StegApp(); // this creates your context. I'm assuming it also creates your RetrieveLogs object, etc
        var username = "UserWithNotMessages"; //this user should exist in your database but should not have any messages. You could insert this user as part of your TestInitialize method
        var password = "UserWithNotMessagesPassword"; //this should be the proper password
        var message = target.RetrieveKeyFn(username, password);
        Assert.AreEqual (-1, message.LogId);
    }

我的单元测试运行良好。我犯的错误是没有将app.config文件复制到测试项目中!尽管说实话,我希望Visual studio无论如何都能做到这一点。

如果它停在Linq语句上,那么它与
戏剧无关
它可能与您的编码方式有关。。您是否可以提供正在抛出的异常(如果有)。。。??另外,调试此代码时,
ConnectionString
的值是多少?例如,您不应该在
dataContext.Connection.Open()上调用Open方法吗。。配置文件中的连接字符串是什么样子的..?请告诉我,和平(单位)要测试的代码数目?测试方法StegAppTest.StegAppTest.RetreiveKeyFnTest引发异常:System.NullReferenceException:对象引用未设置为对象的实例。以下是调试时的字符串减去datbase:metadata=res://*/DataAccess.DataModel.Database.csdl | res://*/DataAccess.DataModel.Database.ssdl | res://*/DataAccess.DataModel.Database.msl;provider=System.Data.SqlClient;provider connection string=“data source=;initial catalog=;user id=;password=;multipleactiveresultsets=True;App=EntityFramework”我做了类似的事情,尽管我发现我必须直接在测试函数中实现连接字符串以及实例化DatabaseEntites对象。我发现我不能直接调用authenicateCredentials fn,但我必须直接在ling语句中写入。这是一种适用的方法吗?您不能将您的Is RetrieveLogs.AuthenticateCredentials调用为public?StegApp是否具有RetrieveLogs类型的公共属性?问题是,如果您正在进行单元测试,通常应该只调用一个方法进行测试。在这种情况下,不应直接调用RetrieveLogs.AuthenticateCredentials。相反,您应该只调用RetrieveKeyFn。在RetrieveKeyFn内部,RetrieveLogs.AuthenticateCredentials将作为您行为的一部分被调用。另一方面,您应该编写另一个只检查AuthenticateCredentials方法的单元测试。