首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >存储库模式的接口有什么特殊用途?

存储库模式的接口有什么特殊用途?
EN

Stack Overflow用户
提问于 2013-08-04 20:42:20
回答 3查看 2.8K关注 0票数 3

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

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

EN

回答 3

Stack Overflow用户

发布于 2013-08-05 05:03:23

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

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

当单元测试时,注入测试的一种方法是通过构造器注入。假设您的存储库具有以下方法:

代码语言:javascript
复制
void Add(Noun noun);
int NumberOfNouns();

这是你的业务类的代码:

代码语言:javascript
复制
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之类的模拟框架来完成此操作,但我将从头开始编写一个模拟类来演示此概念。

代码语言:javascript
复制
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();
    }
}

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

代码语言:javascript
复制
[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点。

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

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

至于抽象类的使用-是的,这将提供相同的能力来提供测试替身。不过,我不确定您会选择将哪些代码放在抽象库中,以及哪些是具体的实现。This answer to an SO question有一个关于抽象类与接口的有趣讨论。

票数 2
EN

Stack Overflow用户

发布于 2013-08-05 13:44:44

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

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

另外,该接口还可以让您更轻松地测试应用程序,因为您可以轻松地mock该接口(或创建stub)

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

票数 1
EN

Stack Overflow用户

发布于 2013-11-12 20:04:22

我发现了一个非常有用的msdn页面,它演示了存储库和测试驱动开发的思想。http://blogs.msdn.com/b/adonet/archive/2009/12/17/walkthrough-test-driven-development-with-the-entity-framework-4-0.aspx

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18043062

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档