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

如何模拟exe签名信息?签名验证测试与流转换问题

问题解答

1. 如何将fileSystem.File.OpenRead()返回的Stream转换为FileStream?

System.IO.Abstractions的MockFile.OpenRead()返回的是MemoryStream,和FileStream属于不同类型,所以用as FileStream转换会返回null。解决这个问题有几种实用思路:

思路一:修改方法依赖,兼容任意Stream

如果FileSignatureInfo.GetFromFileStream()的参数可以改为接受Stream(而非仅FileStream),直接去掉类型转换即可:

public static bool IsSigned(IFileSystem fileSystem, string filePath)
{
    using var stream = fileSystem.File.OpenRead(filePath);
    var signatureInfo = FileSignatureInfo.GetFromFileStream(stream);
    return signatureInfo.State == SignatureState.SignedAndTrusted;
}

如果这个方法是第三方库提供的、无法修改参数,就换下面的思路。

思路二:用真实临时文件替代模拟文件

放弃MockFileSystem,在测试中创建真实的临时无签名exe文件,测试完成后自动清理:

[Test]
public void IsSignedReturnsFalseForUnsignedFile()
{
    // Arrange
    var tempFilePath = Path.Combine(Path.GetTempPath(), "test_unsigned.exe");
    File.WriteAllBytes(tempFilePath, new byte[100]); // 创建空的临时exe文件

    try
    {
        // Act
        var result = MyHelper.IsSigned(new FileSystem(), tempFilePath);

        // Assert
        Assert.IsFalse(result);
    }
    finally
    {
        File.Delete(tempFilePath); // 清理临时文件
    }
}

这种方式能拿到真实的FileStream,保证流程正常执行。

思路三:自定义Mock返回FileStream

如果一定要用MockFileSystem,可以继承它并重写OpenRead方法,返回真实的FileStream(本质还是依赖真实文件):

public class CustomMockFileSystem : MockFileSystem
{
    public override Stream OpenRead(string path)
    {
        // 确保path指向预先准备好的真实文件
        return new FileStream(path, FileMode.Open, FileAccess.Read);
    }
}

但这种方式需要提前准备真实文件,不如临时文件方案直接。


2. 单元测试证书签名验证的最佳方案是什么?

单元测试的核心是测试你的业务逻辑,而非依赖的第三方/系统API。FileSignatureInfo.GetFromFileStream()属于系统或第三方提供的签名验证逻辑,这部分不需要你去测试——你要验证的是:当签名状态为SignedAndTrusted时返回true,其他状态返回false。

最佳实践是抽象依赖,模拟签名验证结果,具体步骤如下:

步骤1:抽象签名验证逻辑

定义接口封装签名验证的调用,隔离对第三方API的依赖:

public interface ISignatureChecker
{
    SignatureState GetSignatureState(Stream stream);
}

public class FileSignatureChecker : ISignatureChecker
{
    public SignatureState GetSignatureState(Stream stream)
    {
        var signatureInfo = FileSignatureInfo.GetFromFileStream(stream as FileStream);
        return signatureInfo.State;
    }
}

步骤2:修改IsSigned方法,注入抽象接口

public static bool IsSigned(IFileSystem fileSystem, ISignatureChecker signatureChecker, string filePath)
{
    using var stream = fileSystem.File.OpenRead(filePath);
    var state = signatureChecker.GetSignatureState(stream);
    return state == SignatureState.SignedAndTrusted;
}

步骤3:编写单元测试,模拟接口返回

用Moq等框架模拟ISignatureChecker的返回值,覆盖不同场景:

[Test]
public void IsSigned_ReturnsFalse_WhenSignatureStateIsNotTrusted()
{
    // Arrange
    var mockFileSystem = new MockFileSystem();
    mockFileSystem.AddFile(@"C:\test\test.exe", new MockFileData("dummy content"));
    var mockChecker = new Mock<ISignatureChecker>();
    mockChecker.Setup(c => c.GetSignatureState(It.IsAny<Stream>())).Returns(SignatureState.NotSigned);

    // Act
    var result = MyHelper.IsSigned(mockFileSystem, mockChecker.Object, @"C:\test\test.exe");

    // Assert
    Assert.IsFalse(result);
}

[Test]
public void IsSigned_ReturnsTrue_WhenSignatureStateIsTrusted()
{
    // Arrange
    var mockFileSystem = new MockFileSystem();
    mockFileSystem.AddFile(@"C:\test\test.exe", new MockFileData("dummy content"));
    var mockChecker = new Mock<ISignatureChecker>();
    mockChecker.Setup(c => c.GetSignatureState(It.IsAny<Stream>())).Returns(SignatureState.SignedAndTrusted);

    // Act
    var result = MyHelper.IsSigned(mockFileSystem, mockChecker.Object, @"C:\test\test.exe");

    // Assert
    Assert.IsTrue(result);
}

补充:集成测试验证完整流程

如果要验证真实的签名验证逻辑(比如确保调用系统API的流程正确),可以做集成测试:准备几个真实的测试文件(无签名、有效签名、无效签名),用真实的FileSystem和FileSignatureChecker测试整个流程。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 20:15:38