C# 抽象类构造函数调用可重写方法
我试图创建一个好的可测试的存储库类来与Moq一起使用。我不想重复我的选择器方法(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 { 保护区
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服务