ASP.NET MVC - 如何在存储库模式中单元测试边界?

时间:2010-05-13 00:47:12

标签: c# asp.net-mvc unit-testing repository-pattern

给定一个基本的存储库接口:

public interface IPersonRepository
{
    void AddPerson(Person person);
    List<Person> GetAllPeople();
}

基本实施:

public class PersonRepository: IPersonRepository
{
    public void AddPerson(Person person) 
    {
        ObjectContext.AddObject(person);
    }

    public List<Person> GetAllPeople()
    {
        return ObjectSet.AsQueryable().ToList();
    }
}

您如何以有意义的方式对此进行单元测试?由于它跨越边界并从数据库进行物理更新和读取,这不是单元测试,而是集成测试。

或者首先想要对其进行单元测试是错误的吗?我应该只对存储库进行集成测试吗?

我一直在谷歌搜索主题,博客经常说要制作一个实现IRepository的存根:

public class PersonRepositoryTestStub: IPersonRepository
{
    private List<Person> people = new List<Person>();
    public void AddPerson(Person person) 
    {
        people.Add(person);
    }

    public List<Person> GetAllPeople()
    {
        return people;
    }
}

但是没有单元测试PersonRepository,它测试PersonRepositoryTestStub的实现(不是很有用)。

4 个答案:

答案 0 :(得分:7)

在这个特定的情况下,我认为你不需要为你的存储库类进行单元测试,因为实现只是调用ObjectContext对象,所以它就像测试你没有构建的东西(这不是主意)。如果您没有任何复杂的逻辑,我的建议是不要浪费时间对该类进行单元测试。你对PersonRepositoryTestStub的看法是对存储库的虚假实现,用于测试DAL之上的层。

答案 1 :(得分:2)

我遇到了同样的问题。我针对我的存储库接口的实现编写了一系列单元测试,这是一个虚假的存储库。完成后不久,我意识到我编写了单元测试来测试虚拟存储库,我编写了虚拟存储库,只是为了支持单元测试。这似乎是一大堆无用的代码。

我得出的结论是,我不需要单元测试,但虚假的存储库实现是好的,因为我可以使用它作为存储库我的服务(因此我的控制器)使用,以便对这些将进行单元测试是可预测的(感谢预定义的假存储库)。

所以,我决定将单元测试留在那里的假存储库中,因为它们有助于测试我的假存储库,这样我可以放心,我的应用程序的更高级别使用完全测试的假货。

换句话说,伪存储库和针对虚拟存储库的单元测试是针对更高级别的应用程序的“支持演员”,以及针对更高级别的应用程序的单元测试。

希望有所帮助。

答案 2 :(得分:1)

我认为这种类型的测试有意义的时候是你的存储库接口是通用的。 E.g。

public interface IEntity
{
    int Id { get; set; }
}

public interface IRepository<TEntity>
    where TEntity : IEntity
{
    void Add(TEntity entity);
    List<TEntity> GetAll();
}

如果您有该接口的多个实现,那么还可以编写一个针对该接口进行测试的通用测试夹具,允许您使用单个测试夹具测试多个存储库实现。这种方法不区分单元测试和集成测试,因为它不知道实现是什么。

如果此类事情让您感兴趣,请告诉我,我可以发布一个完整的例子。

答案 3 :(得分:0)

我将测试直接依赖于DAL实现的业务逻辑层(强烈引用DAL精确实现)或间接(通过接口从DAL抽象)。

我不太喜欢测试,它使用存根实现,只是将数据库调用包装到未注释的事务中(即使抛出异常,也会在测试完成时回滚所有数据更改)。