【问题标题】:How to Moq protected property in C#如何在 C# 中最小起订量受保护的属性
【发布时间】:2018-09-06 17:12:49
【问题描述】:
public class Business {  
    protected List<BusinessRulesDto> BusinessRules { get; set; }  
}

我试过了:

  1. businessMockObject.Protected().SetupSet<List<BusinessRulesDto>>("BusinessRules", ItExpr.IsAny<List<BusinessRulesDto>>()).Verifiable();
    
  2. var businessRulesDtoList = Builder<BusinessRulesDto>.CreateListOfSize(2).Build().ToList();  
    businessMockObject.Protected().SetupGet<List<BusinessRulesDto>>("BusinessRules").Returns(businessRulesDtoList);
    businessMockObject.Protected().SetupSet<List<BusinessRulesDto>>("BusinessRules", ItExpr.IsAny<List<BusinessRulesDto>>()).Verifiable();
    

我尝试了很多东西,但都没有成功。我可以模拟受保护的方法,但不能模拟受保护的属性。

如何模拟受保护的属性?

【问题讨论】:

  • 你总是可以通过反射设置对象。这是关于如何做到这一点的答案stackoverflow.com/questions/1565734/…
  • @Tobias,为什么会这样?为什么模拟受保护的属性意味着架构的弱点?

标签: c# unit-testing moq nbuilder


【解决方案1】:

引擎盖下的模拟创建目标的子类。当目标是具体类(不是接口)时,您要模拟的方法应该是虚拟的,否则子类无法覆盖它并提供Setupped 功能。

【讨论】:

  • 好的。我可以在同一个类中模拟受保护的方法:var eventHookResponseModel = Builder&lt;EventHookResponseModel&gt;.CreateNew().Build(); businessMockObject.Protected().Setup&lt;EventHookResponseModel&gt;("SameTabDataUpdate", ItExpr.IsAny&lt;EventHookModel&gt;()).Returns(eventHookResponseModel).Verifiable(); 正如您指出的方法 SameTabDataUpdate 是受保护的和虚拟的:protected virtual EventHookResponseModel SameTabDataUpdate(EventHookModel eventHookModel)
【解决方案2】:

根据documentation

Moq 4.8 及更高版本允许您通过具有相同成员的完全不相关的类型设置受保护的成员,从而提供 IntelliSense 工作所需的类型信息。您还可以使用此接口设置受保护的泛型方法和具有 by-ref 参数的方法:

在测试项目中创建一个接口来封装被mock的protected成员

public interface IBusinessProtectedMembers {  
    List<BusinessRulesDto> BusinessRules { get; set; }  
}

然后将其与模拟一起使用以利用 IntelliSense

var businessRulesDtoList = Builder<BusinessRulesDto>.CreateListOfSize(2).Build().ToList();
businessMockObject.Protected().As<IBusinessProtectedMembers>()
    .Setup(_ => _.BusinessRules)
    .Returns(businessRulesDtoList);

最后,这一切都取决于 Moq 的要求,即要模拟/存根的成员必须是虚拟的,以便允许框架覆盖成员。

这意味着Business 应该是这样的

public class Business {  
    protected virtual List<BusinessRulesDto> BusinessRules { get; set; }  
}

为了使上述建议起作用。

【讨论】:

  • +1 为答案。你说受保护的方法/属性应该是虚拟的模拟。我如何能够模拟非虚拟的公共方法?我使用的命名空间是:using FizzWare.NBuilder; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; 这是否有效,因为我在模拟的每个类之上都使用了接口?
猜你喜欢
  • 2011-06-15
  • 2010-09-25
  • 2011-12-12
  • 1970-01-01
  • 2010-10-30
  • 2013-04-08
  • 1970-01-01
  • 2011-03-11
相关资源
最近更新 更多