如何Mock ProcessMessageEventArgs对象用于测试方法传参?
问题描述
我正在为如下方法编写测试:
目标测试的业务方法
public async Task ReadServiceBusMessage(ProcessMessageEventArgs args) { // 业务逻辑代码 }
当前测试代码
public async Task Test_ReadServiceBusMessage() { private Mock<ProcessMessageEventArgs> _eventArgs; _eventArgs = new Mock<ProcessMessageEventArgs>(MockBehavior.Strict); await concreteClassObj.ReadServiceBusMessage(_eventArgs.Object); }
执行创建Mock对象的代码(_eventArgs = new Mock<ProcessMessageEventArgs>(MockBehavior.Strict);)时,抛出异常:
Property ProcessMessageEventArgs.Message does not have a setter
需要修改哪些地方让代码正常运行?
解决方案
针对这个问题,有几种可行的修改方式,根据测试场景选择即可:
1. 切换到宽松Mock模式(最简便)
MockBehavior.Strict会强制要求所有被访问的成员都必须提前配置,而ProcessMessageEventArgs.Message只有getter没有setter,Moq无法在严格模式下处理这种情况。换成宽松模式(Moq默认模式,也可显式指定MockBehavior.Loose)即可跳过强制检查:
public async Task Test_ReadServiceBusMessage() { // 用默认宽松模式创建Mock var eventArgsMock = new Mock<ProcessMessageEventArgs>(); // 如果业务代码需要用到Message属性,额外配置它的返回值 eventArgsMock.SetupGet(x => x.Message).Returns(new Mock<ServiceBusMessage>().Object); await concreteClassObj.ReadServiceBusMessage(eventArgsMock.Object); }
2. 手动构造ProcessMessageEventArgs实例
如果Moq模拟不方便,可以直接创建ProcessMessageEventArgs的真实实例,构造时传入必要的依赖对象:
public async Task Test_ReadServiceBusMessage() { // 创建测试用的ServiceBusMessage var testMessage = new ServiceBusMessage("test-content"); // 构造ProcessMessageEventArgs实例(参数需匹配你使用的Azure Service Bus SDK版本) var args = new ProcessMessageEventArgs( testMessage, Mock.Of<ServiceBusReceiver>(), Mock.Of<ServiceBusMessageActions>(), CancellationToken.None ); await concreteClassObj.ReadServiceBusMessage(args); }
3. 针对Strict模式单独配置Message属性的Getter
如果必须使用MockBehavior.Strict,可以通过SetupGet显式配置Message属性的返回值,即使它没有setter:
public async Task Test_ReadServiceBusMessage() { var eventArgsMock = new Mock<ProcessMessageEventArgs>(MockBehavior.Strict); // 显式配置Message属性的getter返回值 eventArgsMock.SetupGet(x => x.Message).Returns(new ServiceBusMessage("test-data")); // 业务代码用到的其他成员也需要逐一配置,比如CompleteAsync方法 eventArgsMock.Setup(x => x.CompleteAsync(It.IsAny<CancellationToken>())).Returns(Task.CompletedTask); await concreteClassObj.ReadServiceBusMessage(eventArgsMock.Object); }
内容的提问来源于stack exchange,提问作者Rajesh Thakur
相关产品推荐
相关产品推荐

