【问题标题】:Unit Testing functions within repository interfaces - ASP.net MVC3 & Moq存储库接口中的单元测试功能 - ASP.net MVC3 & Moq
【发布时间】:2012-04-10 10:53:00
【问题描述】:

我开始编写单元测试并实现了一个很好的存储库模式/起订量,允许我在不使用“真实”数据的情况下测试我的功能。到目前为止一切顺利.. 但是..

在“帖子”IPostRepository 的存储库界面中,我有一个功能: Post getPostByID(int id); 我希望能够从我的 Test 课程中对此进行测试,但无法确定如何进行。

到目前为止,我正在使用这种模式进行测试:

[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);
}

【问题讨论】:

  • populate(10) 如何创建数据?在模拟的object 属性上获得空引用异常通常意味着模拟没有被实例化,但看起来你正在[SetUp] 中这样做。确保[SetUp] 按预期运行可能是值得的。
  • 哦,我想我现在明白了——我读到“object”是空的,我以为你指的是 Mock 的 object 属性。我认为 Marnix 有你的答案
  • @ataddeini 是的,填充只是迭代,添加到模拟中以节省我在每个测试用例中编写相同的 10 行!

标签: asp.net-mvc-3 unit-testing testing moq


【解决方案1】:

我不确定您使用的是什么单元测试框架,但我使用的是 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();
     }
}

我希望这会有所帮助。

【讨论】:

  • 在周末尝试了这些想法的选择,这个很不错!我以后会用的!
【解决方案2】:

如果你想让你的 mock 对象返回一个结果(不是 null),你需要设置它:

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; } );

这可能会使您的设置代码更容易,因为您不需要使用数据来初始化模拟。

【讨论】:

  • 大坝!我非常接近我的想法,我这样做了,但不知道 return() 函数!我稍后会看这个:)
【解决方案3】:

如果您想测试GetPostById 的真实实现,请通过IPostRepository 的真实实现来测试。 Moq(以及一般的模拟)仅适用于您不想使用真实物品的情况。

换句话说,为您的数据库添加一些帖子,新建真正的存储库,调用GetPostById 并对结果进行断言。但这并不是严格意义上的单元测试,而是集成测试,因为它包含了数据库。

【讨论】:

    猜你喜欢
    • 2012-11-27
    • 2017-12-28
    • 1970-01-01
    • 1970-01-01
    • 2020-01-11
    • 1970-01-01
    • 2013-11-03
    • 1970-01-01
    • 2012-01-19
    相关资源
    最近更新 更多