如何测试第三方库中带有internal set属性的对象?
解决第三方库internal属性无法设置的测试问题
针对你遇到的第三方库ResultClass的Succeded属性因internal set无法在测试中设置的问题,提供以下几种可行解决方案:
1. 反射强制设置属性值
通过反射绕过访问修饰符限制,直接设置Succeded属性:
var result = new ResultClass(); // 获取属性并设置值 typeof(ResultClass) .GetProperty("Succeded", BindingFlags.Public | BindingFlags.Instance) .SetValue(result, false); // 在Mock中返回该实例 foreignLibMock.Setup(x => x.Call()) .ReturnsAsync(result);
2. 利用第三方库提供的可Mock抽象
如果第三方库为ResultClass定义了对应的接口(比如IResult),直接Mock该接口而非具体类:
// 假设第三方库存在IResult接口 var mockResult = new Mock<IResult>(); mockResult.SetupGet(x => x.Succeded).Returns(false); foreignLibMock.Setup(x => x.Call()) .ReturnsAsync(mockResult.Object);
3. 配置InternalsVisibleTo特性(需权限支持)
如果能修改第三方库的配置,或者第三方库本身允许对测试程序集开放internal成员,在第三方库的AssemblyInfo.cs中添加:
[assembly: InternalsVisibleTo("你的测试项目名称")]
之后即可在测试中直接设置属性:
foreignLibMock.Setup(x => x.Call()) .ReturnsAsync(new ResultClass { Succeded = false });
4. 封装适配层隔离依赖
如果上述方法都不可行,可封装一层适配类,将第三方对象转换为自己可控的类型,业务逻辑依赖适配层,测试时Mock适配层:
定义适配接口与实现
// 自定义适配接口 public interface IResultWrapper { bool IsSuccess { get; } } // 适配第三方ResultClass public class ResultWrapper : IResultWrapper { private readonly ResultClass _innerResult; public ResultWrapper(ResultClass innerResult) { _innerResult = innerResult; } public bool IsSuccess => _innerResult.Succeded; } // 修改业务类,依赖适配层 public class Sut { private readonly IForeignLib _foreignLib; public Sut(IForeignLib foreignLib) { _foreignLib = foreignLib; } public async Task MethodToTest() { var result = await _foreignLib.Call(); var wrapper = new ResultWrapper(result); if (!wrapper.IsSuccess) { throw new Exception(); } } }
测试代码
public async Task MethodToTest_ThrowsException_WhenResultFailed() { // Mock第三方库返回任意ResultClass实例 var foreignLibMock = new Mock<IForeignLib>(); foreignLibMock.Setup(x => x.Call()) .ReturnsAsync(new ResultClass()); var sut = new Sut(foreignLibMock.Object); await Assert.ThrowsAsync<Exception>(() => sut.MethodToTest()); }
内容的提问来源于stack exchange,提问作者PassionateDeveloper
相关产品推荐
相关产品推荐

