如何使用Moq在单元测试中设置Exception的InnerException
解决Moq无法设置Exception.InnerException的问题
问题原因
你猜的没错,Exception.InnerException不是virtual属性,Moq仅支持对可重写(virtual/abstract)的成员进行Setup操作,因此直接Mock Exception并设置InnerException会抛出NotSupportedException。
解决方案
方案1:直接实例化Exception(推荐)
无需Mock Exception,直接通过Exception的构造函数传入InnerException即可,这是最简洁直接的方式:
var innerException = new Exception("内部异常信息"); var targetException = new Exception("外层异常信息", innerException); // 此时targetException.InnerException即为传入的innerException
方案2:自定义可重写InnerException的Exception子类
如果业务场景确实需要Mock Exception类型,可以自定义一个子类,将InnerException设为可重写:
public class MockableException : Exception { public override Exception InnerException { get; } public MockableException(Exception innerException) { InnerException = innerException; } } // 对自定义子类进行Mock var innerEx = new Exception(); var exceptionMock = new Mock<MockableException>(innerEx); // 支持后续Setup操作(因InnerException已变为可重写) exceptionMock.Setup(e => e.InnerException).Returns(new Exception("新的内部异常"));
方案3:结合反射设置(不推荐)
若必须Mock原生Exception,可开启CallBase让Moq调用基类实现,再通过反射修改InnerException(该方式不够优雅,仅作为特殊场景下的备选):
var exceptionMock = new Mock<Exception> { CallBase = true }; var innerEx = new Exception(); // 通过反射设置私有字段_innerException typeof(Exception) .GetField("_innerException", BindingFlags.Instance | BindingFlags.NonPublic) .SetValue(exceptionMock.Object, innerEx); // 此时exceptionMock.Object.InnerException即为innerEx
内容的提问来源于stack exchange,提问作者Nashmár
相关产品推荐
相关产品推荐

