【发布时间】:2019-03-27 23:40:18
【问题描述】:
我有一些验证逻辑如下
public interface IValidation {
void validate();
}
public class ParameterValidator {
public void validate(IValidation... validations) {
for (IValidation validation : validations) {
validation.validate();
}
}
}
其中一个验证在 StringFormat 上,如下所示
public class StringFormatValidation implements IValidation {
public StringFormatValidation(StringFormatValidator stringFormatValidator, String param) {
...
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (!(obj instanceof StringFormatValidation)) return false;
StringFormatValidation other = (StringFormatValidation) obj;
if (!Objects.equals(this.param, other.param)) return false;
return
Arrays.equals(SerializationUtils.serialize(this.stringFormatValidator),
SerializationUtils.serialize(other.stringFormatValidator));
}
}
其中StringFormatValidator是一个功能接口如下
@FunctionalInterface
public interface StringFormatValidator extends Serializable {
boolean apply(String arg);
}
我已经覆盖了 equals 来比较序列化字节上的 lambda(目前还不确定是否有其他更好的方法)。 我有一个按预期工作的以下单元测试
@Test
public void testEquality() {
StringFormatValidation testFormatValidation1 = new
StringFormatValidation(StringFormatValidators::isCommaSeparated,"test1");
StringFormatValidation testFormatValidation2 = new
StringFormatValidation(StringFormatValidators::isCommaSeparated,"test2");;
Assert.assertEquals(testFormatValidation1, testFormatValidation2);
}
但是当我尝试如下测试调用站点时,
@MockBean
ParameterValidator parameterValidator;
@Captor
ArgumentCaptor<IValidation> argumentCaptor;
@Test
public void testParameterValidations() {
testResource.doSomething(parameter1, "testParam");
Mockito.verify(parameterValidator).validate(argumentCaptor.capture());
List<IValidation> actualValidationList = argumentCaptor.getAllValues();
StringFormatValidation testFormatValidation = new
StringFormatValidation(StringFormatValidators::isCommaSeparated,
"testParam");
Assert.assertTrue(actualValidationList.contains(testFormatValidation));
}
我得到 java.io.NotSerializableException: Non-serializable lambda 参数捕获器中 StringFormatValidation 值的异常。
我不明白 Mockito 的参数 caprtor 中捕获的值如何失去其可序列化的行为,因为它不是模拟值,而是实际在调用站点中创建的。
注意:我已经简化了整体签名和命名,以便只关注手头的问题。
【问题讨论】:
-
请注意,我没有尝试实际代码,这仅基于您的 cmets 和视觉评论:class
StringFormatValidationimplements(误写为extends?!)IValidation不扩展Serializable。您是否可能将它误认为 interfaceStringFormatValidator确实扩展了Serializable?! -
感谢您抽出宝贵时间查看它。我已更正帖子以用工具替换扩展。我没有将
Serializable提供给IValidation,因为我只需要序列化StringFormatValidator功能接口,该接口用作提供lambda 的参数。然后我需要在我的equals方法中序列化这个 lambda。 -
您提到在参数捕获者中为
StringFormatValidation获得NotSerializableException...我错过了什么?你可以说得更详细点吗? P.S.请在回复 cmets 时使用@username,以便用户收到通知。 -
@Morfic 断言语句在
actualValidationList上对testFormatValidation进行包含检查。这只是testFormatValidation与actualValidationList中存在的所有内容的相等。StringFormatValidation的等号是根据StringFormatValidator的反序列化编写的。这无法对StringFormatValidator的实例进行反病毒化,该实例存在于使用参数捕获器填充的actualValidationList中。请注意,在测试本身中创建的testFormatValidation的序列化使用相同的 lambda,工作正常。
标签: java unit-testing lambda mockito