2013-02-28 61 views
0

我在Asp.Net Web API中有3層。使用EF實現控制器層,服務層和存儲庫層。簡單EF函數的單元測試.net

我是新來的單元測試,並有一個簡單的函數,通過他們的id在數據庫中的人,沒有別的。

基本服務層調用

Unit_Work.Person_Repository.GetPersonByID(id); 

和存儲庫這樣處理:

return context.chapters.Where(p=>p.chapterID==id).SingleOrDefault(); 
  1. 我會寫這個是什麼樣的單元測試。
  2. 我應該使用數據庫還是模擬實現。
  3. 我想過使用Sql Server Compact填充模擬人,然後試圖通過ID得到這個人是正確的。

在此先感謝所有那些回答。

回答

-1

您可以使用xml/.csv文件獲取數據。即,您需要從單元測試項目中的xml文件中獲取ID,章節詳細信息。然後你必須傳遞id作爲參數,然後用xml文件中的數據獲取來檢查返回值。如果你不明白,讓我知道。您可以通過添加新項目選項來創建單元測試項目。然後在vs2010上選擇添加xml文件以獲取要測試的數據。

你的第三個問題也是正確的。 u cn填充數據庫中的數據並檢查返回值中的數據

+0

這是你的工作...請讓它作爲答案,如果它可以幫助你。 – 2013-03-01 05:04:44

-1

我建議嘲笑並將實體框架上下文注入到存儲庫中。

我們這樣做是使用類似於http://nuget.org/packages/FakeDbSet/

東西然後我們的單元測試是這樣的:

[TestFixture] 
class UsersControllerTester 
{ 
    private Mock<IMyEntities> mockData = null; 

    [SetUp] 
    public void Setup() 
    { 
     // Create fake data    
     var inMemoryUsers = new InMemoryDbSet<User>(); 
     inMemoryUsers.Add(new User { ID = 1, FIRSTNAME = "Arne", LASTNAME = "Anka", EMAIL = "[email protected]", FULLNAME = "Anka, Arne", USERNAME = "arne.anka" }); 
     inMemoryUsers.Add(new User { ID = 2, FIRSTNAME = "Bertil", LASTNAME = "Björn", EMAIL = "[email protected]", FULLNAME = "Björn, Bertil", USERNAME = "bertil.bjorn" }); 
     inMemoryUsers.Add(new User { ID = 3, FIRSTNAME = "Carl", LASTNAME = "Cool", EMAIL = "[email protected]", FULLNAME = "Cool, Carl", USERNAME = "carl.cool" }); 
     inMemoryUsers.Add(new User { ID = 4, FIRSTNAME = "David", LASTNAME = "Dûsk", EMAIL = "[email protected]", FULLNAME = "Dûsk, David", USERNAME = "david.dusk" }); 

     // Create mock unit of work 
     mockData = new Mock<IMyEntities>(); 
     mockData.Setup(m => m.Users).Returns(inMemoryUsers);  
    } 

    [Test] 
    public void GetUser() 
    {   
     // Test 
     var usersController = new UsersController(mockData.Object); 

     // Invoke 
     User user1 = usersController.GetUser("1");  

     // Assert 
     Assert.NotNull(user1); 
     Assert.AreEqual(1, user1.ID); 
     Assert.AreEqual("Anka", user1.LASTNAME); 
    } 
0

如果您正在使用實體框架,則無法進行單元測試數據訪問層。

Erik Alsmyr提供的解決方案非常錯誤! 看看這裏爲什麼 - What's the point of in memory IDbSet?

當您在內存數據庫集中使用時,您正在將Linq運行到對象。當您使用EF的DbContext時,您的Linq將轉換爲SQL。這是兩件不同的事情!

這是很容易編寫的代碼,將在內存數據庫集(你所有的單元測試將通過,你會很高興),只是第一次嘗試擊中數據庫時發現運行時錯誤。

讓我們稍微修改一下這段代碼。如果我們使用FIRSTNAME,LASTNAME,我不認爲FULLNAME應該有setter。它應該從FIRSTNAME和LASTNAME計算。

class User 
{ 
    public string FIRSTNAME { get; set; } 
    public string LASTNAME { get; set; } 
    public string FULLNAME 
    { 
     get { return string.Format("{0}, {1}", LASTNAME, FIRSTNAME } 
    } 

    User(string firstName, string lastName) 
    { 
     this.FIRSTNAME = firstName; 
     this.LASTNAME = lastName; 
    } 
} 

現在你可以編寫測試這樣的,它會通過(當然,你在控制器實現它之後)

public IMyEntities GetRepoWithUsers(params User[] users) 
{ 
    var inMemoryUsers = new InMemoryDbSet<User>(); 
    var mockData = new Mock<IMyEntities>(); 
    mockData.Setup(m => m.Users).Returns(inMemoryUsers); 
    return mockData.Object;  
} 
[Test] 
public void GetUserByFullname() 
{   
    var ankaArne = new User("Arne", "Anka"); 
    var bjornBertil = new User("Bertil", "Björn"); 
    var repo = GetRepoWithUsers(ankaArne, bjornBertil); 

    var usersController = new UsersController(repo); 

    var found = usersController.GetUser("Anka, Arne");  

    Assert.NotNull(found); 
    Assert.AreEqual("Anka", found.LASTNAME); 
    Assert.AreEqual("Arne", found.FIRSTNAME); 
} 

但是,當你運行它,對「真實」的DbContext和「真實」 DbSet它會拋出,因爲你不能對計算屬性執行Linq查詢。僅限於那些映射到數據庫列的映射。那麼測試的重點是什麼?