2012-04-10 47 views
0

我正在編寫單元測試,並且已經實現了一個很好的存儲庫模式/ moq,以允許我在不使用「真實」數據的情況下測試我的函數。到目前爲止好..但是..存儲庫接口中的單元測試函數 - ASP.net MVC3&Moq

在我的倉庫界面「帖子」 IPostRepository我有一個函數: Post getPostByID(int id); 我希望能夠從我的測試類測試這一點,但不能工作如何。

到目前爲止,我使用這個模式來我的測試:

[SetUp] 
public void Setup() 
{ 
    mock = new Mock<IPostRepository>(); 
} 

[Test] 
public void someTest() 
{ 
    populate(10); //This populates the mock with 10 fake entries 

    //do test here 
} 

在我的功能「someTest」我希望能夠調用/測試功能GetPostById。我可以使用mock.object.getpostbyid找到該功能,但「對象」爲空。

任何幫助,將不勝感激:)

iPostRepository:

public interface IPostRepository 
{ 
    IQueryable<Post> Posts {get;} 

    void SavePost(Post post); 
    Post getPostByID(int id); 
} 
+1

如何填充(10)'創建數據?在mock的''''屬性上獲得一個空引用異常通常意味着該模擬沒有被實例化,但是看起來你正在'[SetUp]'中做這件事。可能值得確保'[SetUp]'按預期運行。 – ataddeini 2012-04-10 11:26:01

+0

哦,我想我現在明白了 - 我讀「對象」爲空,我認爲你的意思是Mock的'object'屬性。我認爲Marnix有你的答案 – ataddeini 2012-04-10 11:27:44

+0

@ataddeini是的,填充只是迭代,增加了模擬,以節省我在每個測試案例中寫同樣的10行! – JustAnotherDeveloper 2012-04-10 12:01:39

回答

1

如果你希望你的模擬對象,以返回結果(不爲空),則需要對其進行設置:

mock.Setup(m => m.GetPostByID(5)).Returns(new Post()); 

返回究竟什麼是你的,當然。

更新:

如果您需要使用方法的參數,你也可以建立一個CallBack。例如:

mock.Setup(m => m.GetPostByID(It.IsAny<int>())) 
    .Callback(id => return new Post{ Id = id; }); 

這可能會讓您的設置代碼更容易,因爲您不需要使用數據來填充模擬。

+0

大壩!我非常接近我的想法,我這樣做,但不知道有關returns()函數!我會在稍後看這個:) – JustAnotherDeveloper 2012-04-10 11:59:50

1

如果你想測試真正落實GetPostById,通過真正落實IPostRepository這樣做。 Moq(和一般的嘲笑)只適用於你不想使用真實事物的情況。

換句話說,用一些帖子填滿你的數據庫,新建實際的倉庫,請撥打GetPostById並對結果做出斷言。儘管這不是嚴格的單元測試,但它是一個集成測試,因爲它包含數據庫。

2

我不確定你正在使用什麼單元測試框架,但我正在使用NUnit。我不是一個單元測試專家,但我知道足夠讓我開始並獲得結果。

我通常有一個服務層,這會打電話給我的職位庫:

public class PostService 
{ 
    private readonly IPostRepository postRepository; 

    public PostService(IPostRepository postRepository) 
    { 
      if (postRepository== null) 
      { 
       throw new ArgumentNullException("postRepository cannot be null.", "postRepository"); 
      } 

      this.postRepository = postRepository; 
    } 

    public Post GetPostById(int id) 
    { 
      return postRepository.GetPostById(id); 
    } 
} 

單元測試看起來是這樣的:

[TestFixture] 
public class PostServiceTests 
{ 
    private PostService sut; 
    private Mock<IPostRepository> postRepositoryMock; 
    private Post post; 

    [SetUp] 
    public void Setup() 
    { 
      postRepositoryMock = new Mock<IPostRepository>(); 

      sut = new PostService(postRepositoryMock.Object); 

      post = new Post 
      { 
       Id = 5 
      }; 
    } 

    [Test] 
    public void GetPostById_should_call_repository_to_get_a_post_by_id() 
    { 
      int id = 5; 
      postRepositoryMock 
       .Setup(x => x.GetPostById(id)) 
       .Returns(post).Verifiable(); 

      // Act 
      Post result = sut.GetPostById(id); 

      // Assert 
      Assert.AreEqual(post, result); 
      postRepositoryMock.Verify(); 
    } 
} 

我希望這有助於。

+0

在週末嘗試了這些想法的選擇,這一個很不錯!我將在未來使用它! – JustAnotherDeveloper 2012-04-16 14:27:31

+0

如果它有幫助,那麼請給它一個投票:) – 2012-04-17 07:49:50