C# 抽象类构造函数调用可重写方法

C# 抽象类构造函数调用可重写方法,c#,moq,abstract-base-class,C#,Moq,Abstract Base Class,我试图创建一个好的可测试的存储库类来与Moq一起使用。我不想重复我的选择器方法(GetAll,Get,…)。我的实现工作正常,但是SonarSource报告了一个错误。有人知道更好的实现吗 var areas=新区域[]{…}; var areaRepositoryMock=new Mock(){CallBase=true}; areaRepositoryMock.Setup(m=>m.Initialize())。返回(区域); 基类 公共抽象类BaseAreaRepository { 保护区

我试图创建一个好的可测试的存储库类来与Moq一起使用。我不想重复我的选择器方法(
GetAll
Get
,…)。我的实现工作正常,但是SonarSource报告了一个错误。有人知道更好的实现吗

var areas=新区域[]{…};
var areaRepositoryMock=new Mock(){CallBase=true};
areaRepositoryMock.Setup(m=>m.Initialize())。返回(区域);
基类

公共抽象类BaseAreaRepository
{
保护区【】;
受保护的BaseAreaRepository()
{
this._areas=this.Initialize();
}
公共抽象区域[]初始化();
公共区域[]GetAll()
{
把这个还给我;
}
公共区域获取(int id)
{
返回此值。_areas.FirstOrDefault(o=>o.Id.Equals(Id));
}
}
MyAreaRepository

公共类MyAreaRepository:BaseAreaRepository
{
公共覆盖区域[]初始化()
{
返回//从其他源加载数据
}
}

如果您只想测试基类,那么我将创建该类的特定于单元测试的实现,并提供任何帮助函数来测试受保护的类。基本上你用MyAreaRepository做了什么,但是作为测试类中的一个私有类,

RSPEC-1699构造函数应该只调用不可重写的方法,它与单元测试没有任何关系,不管你如何测试它,它都会保留在那里

有人知道更好的实现吗

我想提出另一种方法,以避免这种违反,并使您的代码更易于测试

这个想法取代了
base
类使用组合和DI原则

public interface IAreaContext
{
    Area[] GetAreas();
}

public class AreaRepository
{
    private IAreaContext _areaContext;

    protected BaseAreaRepository(IAreaContext areaContext)
    {
        _areaContext = areaContext;
    }

    public Area[] GetAll()
    {
        return _areaContext.GetAreas();
    }
}
然后,您可以定义
IAreaContext
和InText的多个实现:

public class MyAreaContext : IAreaContext
{
    public Area[] GetAreas()
    {
        return //Load data from an other source
    }
}

public class MyOtherAreaContext : IAreaContext
{
    public Area[] GetAreas()
    {
        return //Load data from an other source
    }
}
现在,当您有了这个设置,存储库就可以很容易地针对上下文本身的不同行为进行测试。这只是一个例子来说明这个想法:

//Arrange
var context = new Mock<IAreaContext>();
context.Setup(m => m.GetAreas()).Verifiable();
var sut = new AreaRepository(context.Object);

//Act
var _ = sut.GetAll();

//Assert
context.Verify();
//排列
var context=newmock();
context.Setup(m=>m.GetAreas()).Verifiable();
var sut=新区域存储库(context.Object);
//表演
var=sut.GetAll();
//断言
context.Verify();

不,我想测试另一个依赖于基本类的类。我仍然会使用相同的技巧,只需从
MyAreaRepository
派生测试类,并使用一些模拟数据重写
Initialize()
函数。是否要重写
Initialize
以外的任何内容?
Initialize
从哪里获取数据?@ScottHannen我现在只覆盖Initialize,数据源可以是数据库或Web服务