单元测试中找不到支持AES/CBC/ISO7816-4Padding的提供者问题求助
我之前在项目里也碰到过一模一样的情况:Android真机/模拟器上加密完全正常,但跑本地单元测试就各种报错。大概率是单元测试环境没正确配置SpongyCastle导致的,给你几个实用的排查和解决步骤:
1. 手动在测试环境初始化SpongyCastle提供者
Android系统本身已经集成了安全提供者框架,但本地JVM单元测试环境并没有默认加载SpongyCastle。你需要在测试代码执行前主动添加它:
import org.spongycastle.jce.provider.BouncyCastleProvider; import java.security.Security; public class YourEncryptionTest { // 静态代码块,确保在所有测试方法前执行 static { // 避免重复添加提供者 if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) { Security.addProvider(new BouncyCastleProvider()); } } // 你的测试方法... }
也可以用@BeforeClass注解来完成初始化,效果完全一致。
2. 确认单元测试的依赖配置正确
你用的compile指令在新版Android Gradle插件里已经被implementation替代了,而且要确保测试环境能获取到SpongyCastle的依赖。建议把build.gradle里的依赖改成这样:
// 主项目依赖 implementation "com.madgag.spongycastle:core:1.58.0.0" implementation "com.madgag.spongycastle:prov:1.58.0.0" implementation 'com.madgag.spongycastle:bcpkix-jdk15on:1.58.0.0' // 确保本地单元测试环境能拿到这些包 testImplementation "com.madgag.spongycastle:core:1.58.0.0" testImplementation "com.madgag.spongycastle:prov:1.58.0.0" testImplementation 'com.madgag.spongycastle:bcpkix-jdk15on:1.58.0.0'
如果你的单元测试是仪器化测试(跑在Android设备上的androidTest),还要额外添加androidTestImplementation对应的依赖。
3. 明确指定使用SpongyCastle提供者
有时候测试环境里会存在多个加密提供者冲突(比如系统自带的BouncyCastle和你引入的SpongyCastle),这时候要在创建Cipher的时候明确指定用SpongyCastle:
// 用"SC"作为提供者别名,或者直接用常量全称 Cipher cipher = Cipher.getInstance("AES/CBC/ISO7816-4Padding", "SC"); // 或者 Cipher cipher = Cipher.getInstance("AES/CBC/ISO7816-4Padding", BouncyCastleProvider.PROVIDER_NAME);
这样就不会因为系统默认提供者不支持ISO7816-4Padding填充模式而报错了。
4. 验证测试参数与Android端完全一致
最后检查一下测试代码里的加密参数:密钥长度、IV值、明文的编码方式(比如是否都是UTF-8),有没有因为测试环境的差异导致输入数据不一样。比如有些情况下,测试代码里的字符串转字节数组用了默认Charset,而Android端用了显式的UTF-8,这就会导致加密结果不一致,看起来像是测试失败。
按照这几步排查,基本能解决单元测试不通过的问题。
内容的提问来源于stack exchange,提问作者Diego Palomar

