I have some logic for validation as follows
public interface IValidation {
void validate();
}
public class ParameterValidator {
public void validate(IValidation... validations) {
for (IValidation validation : validations) {
validation.validate();
}
}
}
One of the validation is on StringFormat as follows
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));
}
}
where StringFormatValidator
is a functional interface as follows
@FunctionalInterface
public interface StringFormatValidator extends Serializable {
boolean apply(String arg);
}
I have overriden the equals to compare lambda on serialized bytes(not sure of any other better way as of now). I have a following unit test which works as expected
@Test
public void testEquality() {
StringFormatValidation testFormatValidation1 = new
StringFormatValidation(StringFormatValidators::isCommaSeparated,"test1");
StringFormatValidation testFormatValidation2 = new
StringFormatValidation(StringFormatValidators::isCommaSeparated,"test2");;
Assert.assertEquals(testFormatValidation1, testFormatValidation2);
}
But when I am trying to test the call site as follows,
@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));
}
I get java.io.NotSerializableException: Non-serializable lambda
exception for the StringFormatValidation
value in argument captor.
I don't understand how the captured value in Mockito's argument caprtor looses it's serializable behaviour, given that it's not a mocked value but actually created in the call site.
Note: I have simplified the overall signatures and naming for keeping the focus only at the problem at hand.