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

Bre*_*ogt 2 .net c# nunit unit-testing rhino-mocks

我正在使用.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;
   }
}
Run Code Online (Sandbox Code Playgroud)

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

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());
   }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

我希望soomeone可以帮助我.

Stu*_*ser 5

正如Steven所说,你Assert在上面的代码中反对Mock NewsRepository.

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

您可以使用Mock NewsRepository来测试在您提到的情况下使用的内容INewsRepositoryNewsService ; NewsService将使用你的模拟INewsRepository.

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

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

另外,正如Steven所说,没有必要让NewsRepositoryIoC注入自己的副本,所以:

public class NewsRepository : INewsRepository
{
   private readonly INewsRepository newsRepository;

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

   public IEnumerable<News> FindAll()
   {
      return null;
   }
}
Run Code Online (Sandbox Code Playgroud)

应成为:

public class NewsRepository : INewsRepository
{
   public IEnumerable<News> FindAll()
   {
      return null;
   }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

FindAll_should_return_correct_news
可能成为,例如:
FindAll_AfterAddingTwoNewsItems_ReturnsACollectionWithCountOf2

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