You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 3.1升级至6后Moq单元测试抛出System.InvalidProgramException异常

.NET 6升级后Moq Mock配合StreamWriter抛出异常的解决方法

问题描述

将项目从.NET Core 3.1升级到.NET 6后,如下Moq单元测试抛出System.InvalidProgramException : Cannot create boxed ByRef-like values异常:

public void StreamWriter_Test()
{
var stream = new Mock<Stream>();
stream.Setup(s => s.CanWrite).Returns(true);
using var sw = new StreamWriter(stream.Object);
sw.WriteLine("Test");
sw.Flush();
}

异常堆栈跟踪:

StreamProxy.Write(ReadOnlySpan`1 buffer)
StreamWriter.Flush(Boolean flushStream, Boolean flushEncoder)
StreamWriter.Flush()

注:移除sw.WriteLine("Test");后测试可正常执行。

原因分析

.NET 6中StreamWriter的内部实现发生变更,会调用Stream的Write(ReadOnlySpan<byte>)方法。而ReadOnlySpan<T>属于by-ref-like类型,这类类型无法被装箱,Moq在生成Stream的动态代理类时,无法正确处理该方法的调用逻辑,从而触发异常。

解决方案

方案一:使用真实MemoryStream替代Mock

这是最简洁可靠的方案,测试StreamWriter的行为时,真实的MemoryStream既可以完成功能测试,还能直接验证写入内容:

public void StreamWriter_Test()
{
    using var stream = new MemoryStream();
    using var sw = new StreamWriter(stream);
    sw.WriteLine("Test");
    sw.Flush();

    // 验证写入内容(可选)
    stream.Position = 0;
    using var reader = new StreamReader(stream);
    Assert.Equal("Test", reader.ReadLine());
}

方案二:手动Setup Stream的Write(ReadOnlySpan)方法

如果业务场景必须使用Moq,可以手动Setup该Span重载的Write方法,避免Moq生成有问题的代理代码:

public void StreamWriter_Test()
{
    var stream = new Mock<Stream>();
    stream.Setup(s => s.CanWrite).Returns(true);
    
    // 显式Setup ReadOnlySpan<byte>版本的Write方法
    stream.Setup(s => s.Write(It.IsAny<ReadOnlySpan<byte>>()))
          .Callback((ReadOnlySpan<byte> buffer) => 
          {
              // 可在此添加自定义逻辑,比如记录写入的字节内容
          });

    using var sw = new StreamWriter(stream.Object);
    sw.WriteLine("Test");
    sw.Flush();

    // 验证Write方法被调用(可选)
    stream.Verify(s => s.Write(It.IsAny<ReadOnlySpan<byte>>()), Times.AtLeastOnce);
}

另外建议确保Moq版本升级至最新(如4.18及以上),新版本对ref-like类型的支持有优化,但上述两种方案依然是更稳妥的选择。

内容的提问来源于stack exchange,提问作者Rohit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 21:27:36