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

标签 c# .net unit-testing nunit 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;
   }
}

我的单元测试是这样的:

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 中失败?

很抱歉所有问题,但他们是新手问题:)

我希望有人能帮助我。

最佳答案

正如 Steven 所说,您在上面的代码中针对 Mock NewsRepository Asserting。

模拟的想法是隔离被测代码并创建假代码来替换它们的依赖项

您使用 Mock NewsRepository 来测试使用 INewsRepository 的内容,在您的情况下,您提到了 NewsServiceNewsService 将使用您模拟的 INewsRepository

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

如果你想测试调用你的服务层的东西,你需要模拟 NewsService

此外,正如 Steven 所说,NewsRepository 不需要由 IoC 注入(inject)其自身的副本,因此:

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 Testing模拟对象的初始化最好从 Setup 方法中删除,并在方法开始时调用的辅助方法中执行。由于对 Setup 的调用将是不可见的,并且使模拟的初始化不清楚。

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

FindAll_should_return_correct_news
可以变成,例如:
FindAll_AfterAddingTwoNewsItems_ReturnsACollectionWithCountOf2

我希望这能让方法更清晰。

关于c# - 单元测试存储库需要帮助/建议,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4398723/

相关文章:

c# - Xamarin 固定导航栏

c# - 在 MySQL 中使用子类型时遇到问题

c# - 在 Moq 中为返回 void 的方法分配参数

visual-studio - 是否存在为 .NET 类预编写单元测试的工具?

ruby-on-rails - 有没有办法在 Vim 中运行单个集中的 Shoulda 测试或上下文(可能使用rails.vim)?

c# - BitmapSource 作为图像控件的源

更改属性时,C# XAML 数据绑定(bind)无效

c# - Entity Framework Core 中的添加迁移错误

c# - IEnumerable<T> 线程安全?

java - 如何模拟传递给构造函数的参数