使用Moq模拟RabbitMQ泛型BasicPublishAsync方法的参数配置疑问
Moq模拟RabbitMQ泛型BasicPublishAsync方法的参数配置疑问
嘿,我来帮你解决这个Moq匹配泛型参数的问题!
首先得指出你当前代码里的一个小问题:你在BasicPublishAsync<It.IsSubtype<IAmqpHeader>>这里用It.IsSubtype作为泛型参数是不对的——Moq的匹配器不能直接放在泛型参数位置,泛型参数得是符合约束的实际类型,或者我们换个写法让Moq自动推断。
针对你第四个参数(basicProperties)的配置需求,分两种场景给你方案:
场景1:不关心basicProperties的具体值,只要符合接口约束就行
这种情况最简单,我们可以利用Moq的泛型Setup方法,加上和原方法一致的泛型约束,直接用It.IsAny<TProperties>来匹配:
mockRabbitModel.Setup<TProperties>(a => a.BasicPublishAsync( It.IsAny<string>(), It.IsAny<string>(), It.IsAny<bool>(), It.IsAny<TProperties>(), // 匹配任意符合约束的TProperties实例 It.Is<ReadOnlyMemory<byte>>(b => this.TestSentMessage(b, (expected, actual) => Assert.AreEqual(expected, actual.Command))), It.IsAny<CancellationToken>())) where TProperties : IReadOnlyBasicProperties, IAmqpHeader;
这样写的话,Moq就能正确识别泛型参数的约束,匹配所有符合条件的TProperties实例。
场景2:需要验证basicProperties的具体属性(比如Headers里的某个值)
如果你要检查basicProperties的特定内容,比如是否包含某个自定义Header,可以用It.Is<TProperties>结合条件判断:
mockRabbitModel.Setup<TProperties>(a => a.BasicPublishAsync( It.IsAny<string>(), It.IsAny<string>(), It.IsAny<bool>(), It.Is<TProperties>(p => p.Headers != null && p.Headers.ContainsKey("x-custom-header")), // 自定义验证逻辑 It.Is<ReadOnlyMemory<byte>>(b => this.TestSentMessage(b, (expected, actual) => Assert.AreEqual(expected, actual.Command))), It.IsAny<CancellationToken>())) where TProperties : IReadOnlyBasicProperties, IAmqpHeader;
另一种简化写法:让Moq自动推断泛型参数
如果你不想显式写泛型Setup,也可以直接用接口类型来匹配参数,因为TProperties必须实现IReadOnlyBasicProperties,所以Moq会自动兼容子类型的匹配:
mockRabbitModel.Setup(a => a.BasicPublishAsync( It.IsAny<string>(), It.IsAny<string>(), It.IsAny<bool>(), It.IsAny<IReadOnlyBasicProperties>(), // 利用接口多态匹配 It.Is<ReadOnlyMemory<byte>>(b => this.TestSentMessage(b, (expected, actual) => Assert.AreEqual(expected, actual.Command))), It.IsAny<CancellationToken>()));
要是你想更严格,确保参数同时实现两个接口,也可以这么写:
It.Is<object>(p => p is IReadOnlyBasicProperties && p is IAmqpHeader)
把上面这段替换掉It.IsAny<IReadOnlyBasicProperties>()就行。
备注:内容来源于stack exchange,提问作者MCFH
相关产品推荐
相关产品推荐

