繁体   English   中英

单元测试存储库需要帮助/建议

[英]Help/advice needed with unit testing repositories

我正在使用.NET 4,NUnit和Rhino模拟。 我想对我的新闻库进行单元测试,但我不确定如何去做。 我的新闻存储库是我最终将用于与数据库通信的内容。 我想用它来测试假/伪数据。 不确定是否可能? 这就是我目前拥有的:

public interface INewsRepository
{
   IEnumerable<News> FindAll();
}

public class NewsRepository : INewsRepository
{
   private readonly INewsRepository newsRepository;

   public NewsRepository(INewsRepository newsRepository)
   {
      this.newsRepository = newsRepository;
   }

   public IEnumerable<News> FindAll()
   {
      return null;
   }
}

我的单元测试看起来像这样:

public class NewsRepositoryTest
{
   private INewsRepository newsRepository;

   [SetUp]
   public void Init()
   {
      newsRepository = MockRepository.GenerateMock<NewsRepository>();
   }

   [Test]
   public void FindAll_should_return_correct_news()
   {
      // Arrange
      List<News> newsList = new List<News>();
      newsList.Add(new News { Id = 1, Title = "Test Title 1" });
      newsList.Add(new News { Id = 2, Title = "Test Title 2" });

      newsRepository.Stub(r => r.FindAll()).Return(newsList);

      // Act
      var actual = newsRepository.FindAll();

      // Assert
      Assert.AreEqual(2, actual.Count());
   }
}

在上面的代码中,我不确定我需要模拟什么。 上面的代码编译但在NUnit GUI中关于构造函数值失败。 我只能假设它与我需要提供给NewsRepository的INewsRepository参数有关。 我不知道如何在测试中做到这一点。 有人可以纠正我的单元测试,以便它将通过NUnit GUI吗? 如果我正确实施我的存储库,有人也可以提供一些反馈吗?

作为嘲笑的新手,有什么我需要验证的吗? 我什么时候需要验证? 它的目的是什么? 我一直在研究几个源代码项目,有些使用验证,有些则没有。

如果上述测试通过,这对我作为开发人员的证明是什么? 另一个开发人员必须对我的存储库做什么才能使其在NUnit GUI中失败?

对不起所有的问题,但他们是新手问题:)

我希望soomeone可以帮助我。

正如史蒂文所说的那样,你在上面的代码中对Mock NewsRepository进行了Assert

模拟的想法是隔离“受测试代码”并创建伪造来替换它们的依赖项

您使用Mock NewsRepository来测试使用INewsRepository东西,在您的情况下,您提到了NewsService ; NewsService将使用您的INewsRepository模拟。

如果您在解决方案中搜索使用INewsRepository.FindAll()的任何内容,您将创建一个Mock Repository来单独测试该代码。

如果您想测试调用Service层的内容,则需要模拟NewsService

此外,正如史蒂文所说, NewsRepository没有必要拥有由IoC注入的自身副本,因此:

public class NewsRepository : INewsRepository
{
   private readonly INewsRepository newsRepository;

   public NewsRepository(INewsRepository newsRepository)
   {
      this.newsRepository = newsRepository;
   }

   public IEnumerable<News> FindAll()
   {
      return null;
   }
}

应成为:

public class NewsRepository : INewsRepository
{
   public IEnumerable<News> FindAll()
   {
      return null;
   }
}

一旦在FindAll()方法中有需要测试的功能,就可以模拟它们使用的对象

作为一个伟大的Art Of Unit测试的风格点,模拟对象的初始化最好不在Setup方法中,而是在方法开始时调用的辅助方法中执行。 由于对安装程序的调用将是不可见的,并使模拟的初始化不清楚。

作为另一种风格,从该书中,建议的单元测试命名约定是:“ MethodUnderTest_Scenario_ExpectedBehavior ”。 所以,

FindAll_should_return_correct_news
可能成为,例如:
FindAll_AfterAddingTwoNewsItems_ReturnsACollectionWithCountOf2

我希望这会使方法更清晰。

您的FindAll_should_return_correct_news测试方法不测试存储库,它正在测试自己。 当您将其简化为真正的功能时,您可以看到这一点:

[Test]
public void FindAll_should_return_correct_news()
{
   // Arrange
   List<News> newsList = new List<News>();
   newsList.Add(new News { Id = 1, Title = "Test Title 1" });
   newsList.Add(new News { Id = 2, Title = "Test Title 2" });

   // Act
   var actual = newsList;

   // Assert
   Assert.AreEqual(2, actual.Count());
}

正如您所看到的,您基本上正在做的是创建一个列表,填充它并测试它是否实际包含您放入其中的记录数。

当您的存储库除了数据库交互之外什么也不做(因此没有应用程序逻辑)时,没有什么可以使用单元测试来测试。 您可以通过编写存储库的集成测试来解决此问题。 你基本上可以用这样的集成测试做的是在测试数据库中插入一些记录(虽然使用真实的数据库,而不是内存数据库)然后调用真实的存储库类来查看它是否从测试中获取预期的记录数据库。 所有这些都应该在事务中执行,并在测试结束时回滚(这可以确保这些测试值得信赖)。

当您使用允许编写LINQ查询的O / RM工具时,您也可以尝试不同的方法。 您可以伪造LINQ提供程序,如本文所示

可能想通过ayende阅读这篇文章

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM