C# 如何在派生类中模拟基方法?

C# 如何在派生类中模拟基方法?,c#,moq,C#,Moq,我想模拟方法base.Generate(操作、模型、生成器、false): 公共类扩展SQLServerMigrationSqlGenerator:SQLServerMigrationSqlGenerator { 公共扩展SQLServerMigrationSqlGenerator(MigrationSqlGeneratorDependencies依赖项,IMiglationAnnotationProvider MigrationAnnotations):基本(依赖项,迁移注释){} //这种方

我想模拟方法
base.Generate(操作、模型、生成器、false)

公共类扩展SQLServerMigrationSqlGenerator:SQLServerMigrationSqlGenerator { 公共扩展SQLServerMigrationSqlGenerator(MigrationSqlGeneratorDependencies依赖项,IMiglationAnnotationProvider MigrationAnnotations):基本(依赖项,迁移注释){} //这种方法应该进行测试 受保护的重写void Generate(CreateIndexOperation操作、IModel模型、MigrationCommandListBuilder生成器、bool终止) { Generate(operation,model,builder,false);//这一行应该被模拟 AddIncludeIndex(操作、生成器、终止); } 受保护的void AddIncludeIndex(CreateIndexOperation操作、MigrationCommandListBuilder生成器、bool终止) { //一些代码 } public void GenerateTest(CreateIndexOperation操作、IModel模型、MigrationCommandListBuilder构建器、bool终止) { 生成(操作、模型、生成器、终止); }
我使用的模拟设置是:

var sut = new Mock<ExtendedSqlServerMigrationsSqlGenerator>(GetDependencies(), p2.Object) 
{ 
 CallBase = true 
};
sut.Protected().Setup("Generate", true, ItExpr.IsAny<CreateIndexOperation>(), ItExpr.IsAny<IModel>(), ItExpr.IsAny<MigrationCommandListBuilder>(), ItExpr.IsAny<bool>());
sut.Object.GenerateTest(createIndexOperation.Object, new Model(), m3.Object, false);
var sut=new Mock(GetDependencies(),p2.Object)
{ 
CallBase=true
};
sut.Protected().Setup(“Generate”,true,ItExpr.IsAny(),ItExpr.IsAny(),ItExpr.IsAny(),ItExpr.IsAny());
sut.Object.GenerateTest(createIndexOperation.Object,new Model(),m3.Object,false);
目前我调用
GenerateTest()
。 问题是,
Generated
方法是模拟的,而不是
base.Generate
我还尝试设置一个派生的TestClass,它允许我从TestClass调用受保护的方法。但问题相同

这与不同。我知道如何模拟对基类methode的调用,但不知道如何模拟同一个methode

有关该课程的一些背景信息

EF可以基于模型生成SQL语句。为了扩展生成的SQL,我将DI中的此类替换为派生类。当EF调用
generate
时,我必须调用基类,然后添加一些额外的SQL语句

我想模拟'base.generate'的原因是

  • 配置有效参数并不容易
  • 我对基类的实现细节不感兴趣

这个场景似乎不是唯一的,应该有一个简单的方法来模拟它。

虽然我认为您试图解决的问题在广义上非常有效,特别是当基类发出您想要避免的系统/IO调用时,我会指出中的响应,表明Moq不是正确的工具

Moq旨在从sut中删除依赖项,而不是替换sut中的功能。这是有意义的,因为sut中的函数通常会产生副作用(特别是当您尝试替换的函数的返回类型为空时)


从历史上看,当我使用EF进行这种性质的测试时,我发现为每个测试类(或测试程序集)启动一个localDb更方便、更可靠执行集成测试,而不是为了单元测试而尝试进行单元测试。当然,这里有一些依赖项,您首先使用代码进行迁移等等。

而我认为您试图解决的问题在广义上非常有效,特别是当基类发出您想要的系统/IO调用时oid,我会指出中的回答,以表明Moq不是这里的正确工具

Moq旨在从sut中删除依赖项,而不是替换sut中的功能。这是有意义的,因为sut中的函数通常会产生副作用(特别是当您尝试替换的函数的返回类型为空时)


从历史上看,当我使用EF进行这种性质的测试时,我发现为每个测试类(或测试程序集)启动一个localDb更方便、更可靠并执行集成测试,而不是为了单元测试而尝试进行单元测试。当然,这里有一些依赖项,您是在迁移等过程中首先使用代码的。

我有点困惑,为什么您要尝试从基类开始模拟实现。如果您正确地模拟了Generate方法,基类Generate方法根本不应该被调用。我错了吗?我在代码中添加了一些注释,我想测试哪种方法,哪种基类调用应该被模拟。这更清楚了。嗯……所以我要问自己的问题是,这是否是Mock设计用来帮助您的。这个框架帮助您删除dependencies,但在本例中,您试图删除对基类的依赖,这是一个奇怪的概念,尤其是如果/因为base.Generate()方法有副作用。但同时,我发现有些情况下,基本方法会进行系统调用,而您更愿意避免。请看中的第二个答案。我认为这在一定程度上反映了我的感受。我的直觉反应是,由于您在实践中看到的所有副作用,最好在th LocalDbI有点困惑,为什么您要开始模拟基类中的实现。如果您正确模拟了Generate方法的实现,则根本不应该调用基类Generate方法。我错了吗?我在代码中添加了一些注释,说明了我要测试的方法和应该使用的基类调用mocked.使这一点更清楚。嗯…所以我问自己的问题是,Mock是否是为了帮助您而设计的。这个框架帮助您删除依赖项,但在本例中,您试图删除对基类的依赖项,这只是一个奇怪的概念,尤其是如果/因为base.Generate()方法有很多优点