【发布时间】:2019-08-13 21:54:27
【问题描述】:
我想mock下面代码的方法base.Generate(operation, model, builder, false);:
public class ExtendedSqlServerMigrationsSqlGenerator : SqlServerMigrationsSqlGenerator
{
public ExtendedSqlServerMigrationsSqlGenerator(MigrationsSqlGeneratorDependencies dependencies, IMigrationsAnnotationProvider migrationsAnnotations) :base(dependencies, migrationsAnnotations){}
// this methode should be tested
protected override void Generate(CreateIndexOperation operation, IModel model, MigrationCommandListBuilder builder, bool terminate)
{
base.Generate(operation, model, builder, false); // this line should be mocked
AddIncludeIndex(operation, builder, terminate);
}
protected void AddIncludeIndex(CreateIndexOperation operation, MigrationCommandListBuilder builder, bool terminate)
{
//some code
}
public void GenerateTest(CreateIndexOperation operation, IModel model, MigrationCommandListBuilder builder, bool terminate)
{
Generate(operation, model, builder, terminate);
}
我使用的模拟设置是:
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);
目前我打电话给GenerateTest()。
问题是 Generated 方法被模拟而不是 base.Generate 我还尝试设置派生的 TestClass,它允许我从 testclass 调用受保护的方法。但同样的问题。
这与Mocking a protected member without reflection 不同。我知道如何模拟对基类方法的调用,但不知道如何模拟相同的方法。
关于这个类的一些背景信息
EF 可以基于 Model 生成 SQL 语句。为了扩展生成的 SQL,我将 DI 中的这个类替换为派生类。当 EF 调用 generate 时,我必须调用基类并添加一些额外的 SQL 语句。
我想模拟 `base.generate' 的原因是
- 配置有效参数并不容易
- 我对基类的实现细节不感兴趣。
这种情况似乎不是唯一的,并且期望有一种简单的方法来模拟它。
【问题讨论】:
-
我有点困惑,为什么你要开始模拟基类中的实现。如果您正确地模拟了 Generate 方法的实现,则根本不应调用基类 Generate 方法。我错了吗?
-
我在代码中添加了一些注释,我想测试哪个方法以及应该模拟哪个基本调用。让这一点更清楚。
-
嗯.. 所以我问自己的问题是,这是否是 Mock 旨在帮助您解决的问题。该框架可帮助您删除依赖项,但在这种情况下,您正在尝试删除对基类的依赖项,这只是一个让我难以理解的奇怪概念,尤其是如果/因为 base.Generate() 方法有边效果。但与此同时,我知道在某些情况下,基本方法会进行您宁愿避免的系统调用..
-
看看this SO post的第二个答案。我认为这部分反映了我在这里的感受。我的直觉反应是,由于您在实践中会看到所有副作用,最好使用 LocalDb 运行集成测试