3

我完全理解存储库模式的设计思想。但是为什么我们需要实现 iDepository 接口类呢?这有什么特殊用途?存储库类本身可以在没有接口类的情况下工作。

我想有人会回答我这是为了从业务逻辑和数据逻辑中解耦。但是即使没有接口类,数据逻辑不就是解耦了数据逻辑吗?

4

3 回答 3

2

这样您就可以在对业务层进行单元测试时注入 IRepository 类的测试替身。这有以下好处:

  1. 它使您可以轻松地确定失败的测试是由业务层而不是存储库层引起的;
  2. 它使您的业务逻辑层测试速度更快,因为它们既不依赖于往往很慢的数据访问,也不依赖于往往很慢的数据库结构和测试数据的设置。

单元测试时注入测试的一种方法是构造函数注入。假设您的存储库具有以下方法:

void Add(Noun noun);
int NumberOfNouns();

这是您的商务舱的代码:

public class BusinessClass {

    private IRepository _repository;

    public BusinessClass(IRepository repository) {
        _repository = repository;
    }

    // optionally, you can make your default constructor create an instance
    // of your default repository
    public BusinessClass() {
        _repository = new Repository();
    }

    // method which will be tested 
    public AddNoun(string noun) {
        _repository.Add(new Noun(noun));
    }
}

要在不需要真实存储库的情况下测试 AddNoun,您需要设置一个测试替身。通常你会通过使用 Moq 等模拟框架来做到这一点,但我将从头开始编写一个模拟类来说明这个概念。

public IRepository MockRepository : IRepository {
    private List<Noun> nouns = new List<Noun>();

    public void Add(Noun noun) {
        nouns.Add(noun);
    }

    public int NumberOfNouns() {
        return nouns.Count();
    }
}

现在你的测试之一可能是这个。

[Test]
public void AddingNounShouldIncreaseNounCountByOne() {
    // Arrange
    var mockRepository = new MockRepository();
    var businessClassToTest = new BusinessClass(mockRepository);

    // Act
    businessClassToTest.Add("cat");

    // Assert
    Assert.AreEqual(1, mockRepository.NumberOfNouns(), "Number of nouns in repository should have increased after calling AddNoun");

}

这样做的结果是您现在已经测试了 BusinessClass.AddNoun 方法的功能,而无需接触数据库。这意味着即使您的存储库层出现问题(例如连接字符串的问题),您也可以确保您的业务层按预期工作。这涵盖了上面的第 1 点。

至于上面的第 2 点,每当您编写测试数据库的测试时,您应该确保它在每次测试之前处于已知状态。这通常涉及在每次测试开始时删除所有数据并重新添加测试数据。如果不这样做,那么您将无法针对表中的行数运行断言,因为您无法确定应该是什么。

删除和重新添加测试数据通常是通过运行 SQL 脚本来完成的,当数据库结构发生变化时,这些脚本速度很慢并且容易受到破坏。因此,建议将数据库的使用仅限于存储库本身的测试,并在对应用程序的其他方面进行单元测试时使用模拟存储库。

至于抽象类的使用——是的,这将提供相同的能力来提供测试替身。不过,我不确定您会选择将哪些代码放入抽象库以及具体实现中。这个 SO question 的答案对抽象类与交互进行了有趣的讨论。

于 2013-08-04T21:03:23.400 回答
1

首先,您必须了解存储库模式是什么。它是一个抽象层,因此应用程序的其余部分不必关心数据的来源。

.NET 中的抽象通常由接口表示,因为没有逻辑(代码)可以附加到接口。

作为奖励,该接口还使您可以更轻松地测试应用程序,因为您可以轻松地模拟接口(或创建存根

该界面还允许您发展数据层。例如,您可以从对所有存储库类使用数据库开始。但是稍后您想在 Web 服务后面移动一些逻辑。然后,您只需将 DB 存储库替换为 WCF 存储库。您可能还会发现存储库很慢,并希望在其中实现简单的内存缓存(通过使用 memcache 或其他东西)

于 2013-08-05T05:44:43.870 回答
0

我发现了一个非常有用的 msdn 页面,展示了 Repository 和 Test Driven Development 的想法。 http://blogs.msdn.com/b/adonet/archive/2009/12/17/walkthrough-test-driven-development-with-the-entity-framework-4-0.aspx

于 2013-11-12T12:04:22.103 回答