2013-01-20 125 views
0

嘗試訪問實體框架的單元測試函數。所以我試圖把所有的實體代碼放到下面的測試函數中?然而它停止在Linq聲明中;顯然試圖訪問數據庫對它來說太過戲劇化了。也許一個解決方法是在基於sql lite或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"); 
     } 


    } 
+1

如果停在Linq聲明中,它與'Drama'無關,它與你編碼的可能性有關。你可以提供一個正在拋出的異常,如果有的話......?當你調試這個代碼時'ConnectionString'的值是什麼? – MethodMan

+1

例如,不應該在'dataContext.Connection.Open()'上調用Open方法..連接字符串在配置文件中看起來像什麼..? – MethodMan

+1

請讓我知道,你想測試什麼和平(單位)的代碼? –

回答

0

我得到了我的單元測試,以做工精細的例子。我所犯的錯誤不是將app.config文件複製到測試項目中!儘管說實話,我預計Visual Studio會做到這一點。

2

首先,你應該能夠訪問同一個數據庫中測試應用程序作爲一個你用在主/實際應用。你只需要確保你的Test項目包含你自己的App.config中的連接字符串。

上下文的初始化應該在您的StegApp()中的裏面中完成,或者您應該能夠從另一個範圍傳遞上下文到您的StegApp()。從我讀到的代碼中,您的StegApp()將無法訪問您創建的dataContext變量。

您對null用戶的測試已經發生在AuthenticateCredentials()方法下的RetrieveKeyFn()內部,因此不需要第一個「Assert.IsNotNull(user)」。我建議將您的用於UI行爲的RetrieveKeyFn業務邏輯分開,以便您可以輕鬆地進行單元測試。您可以綁定「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); 
    } 
+0

我做了類似的事情,雖然我發現我不得不直接在測試函數中實現連接字符串,並且實例化了DatabaseEntites的一個對象。我發現我無法儘快致電authenicateCredentials,但我必須直接寫Ling語句。這是一種適用的方法嗎? – David

+0

你不能調用你的RetrieveLogs.AuthenticateCredentials公共嗎? StegApp是否有一個RetrieveLogs類型的公共屬性?這是事情,如果你正在做單元測試,你通常應該只調用一種方法來測試。在這種情況下,您不應直接調用RetrieveLogs.AuthenticateCredentials。相反,你只應該調用RetrieveKeyFn。在RetrieveKeyFn中,RetrieveLogs.AuthenticateCredentials將作爲您的行爲的一部分被調用。另一方面,您應該編寫另一個單元測試,僅檢查AuthenticateCredentials方法。 –