C# xUnit单元测试构造函数中Moq配置值为空问题解决
问题原因
测试失败是3处Moq配置和代码写法错误导致的:
IOptions<CallOptions>的Mock配置完全无效:options.SetReturnsDefault("test")是给Mock对象自身的方法返回设置默认值,根本没有配置IOptions.Value属性返回合法的CallOptions实例,构造函数读取_options.Name时拿到的是空值,自然触发非空校验抛异常。CreateSut方法存在两处笔误:一是构造函数传参顺序颠倒,Country构造函数第一个参数是IOptions实例、第二个是Irepo实例,你写反了传入顺序;二是引用的Mock变量名不匹配,定义的变量名是options,调用时写的是_options,会直接触发编译错误。- Irepo的Mock参数匹配类型错误:你Setup和Verify时用
It.IsAny<List<string>>()匹配参数,但测试调用时传入的是string[]数组,二者类型不匹配,后续即使构造成功也会导致Verify失败。
*额外注意:你贴的业务类构造函数泛型参数有误,_options是CallOptions类型,构造函数参数应该写为IOptions<CallOptions> options,否则会出现泛型不匹配的编译错误。
修复方案
按以下步骤调整测试代码即可:
- 正确配置IOptions Mock的
Value属性,返回Name非空的CallOptions实例 - 修正
CreateSut中构造函数的传参顺序,统一Mock变量命名 - 将Irepo相关Setup、Verify的参数匹配泛型改为
IList<string>,和方法签名保持一致,兼容传入的数组类型
修正后的完整测试代码
public class ProcessorTests { private readonly Mock<Irepo> _repositoryMock; private readonly Mock<IOptions<CallOptions>> _optionsMock; public ProcessorTests() { _repositoryMock = new Mock<Irepo>(); _optionsMock = new Mock<IOptions<CallOptions>>(); // 正确配置IOptions的Value属性,返回Name非空的合法配置 _optionsMock.Setup(o => o.Value).Returns(new CallOptions { Name = "test" }); } private Country<CountryModel> CreateSut() { // 修正传参顺序:第一个是IOptions实例,第二个是Irepo实例 return new Country<CountryModel>(_optionsMock.Object, _repositoryMock.Object); } [Fact] public async Task ShouldCheck() { GetRepoMock(); await CreateSut().ProcessCall(new string[] { "TEST" }); // 参数匹配改为IList<string>,兼容数组传入 _repositoryMock.Verify(x => x.set(It.IsAny<IList<string>>()), Times.Once); } private void GetRepoMock() { // 参数匹配改为IList<string>,和方法签名保持一致 _repositoryMock .Setup(m => m.set(It.IsAny<IList<string>>())) .ReturnsAsync(new Response<Code>(false, null, Enumerable.Empty<Code>())); } }
补充:如果要覆盖构造函数的非空校验逻辑,可以单独写测试用例,配置IOptions返回Name为空的CallOptions,断言构造时抛出预期的ArgumentException即可。
内容的提问来源于stack exchange,提问作者amd
相关产品推荐
相关产品推荐

