Reputation: 30273
I'm trying to look into the structure of a ValidationBuilder
instance, used like so:
validationBuilder = validationBuilder.add(
!(dateEnd != null && !ad.endDate().equals(dateEnd) && dateEnd.compareTo(dateBegin) <= 0),
" End date must be after start date.");
Stopping at a breakpoint just past this line, though, this is all I see:
That is, I expected, under validationBuilder
or validation
, to see some List
type member aggregating errors. However, all I see is value
, corresponding to an instance of the templated type for the class ValidationBuilder
, i.e.
ValidationBuilder<AdRequest> validationBuilder = ValidationBuilder.from(adRequest);
Now, here's (parts of) the decompiled .class file. (Left out the imports, copy constructor, and build method.)
public class ValidationBuilder<T> {
private final Validation<Array<String>, T> validation;
public static <T> ValidationBuilder<T> from(T testObject) {
return new ValidationBuilder(testObject);
}
// ...
public ValidationBuilder<T> add(boolean testSucceeded, String error) {
if (testSucceeded) {
return this;
} else {
Validation<Array<String>, T> invalid = (Validation)this.validation.fold((errors) -> {
return Validation.invalid(errors.append(error));
}, (testObject) -> {
return Validation.invalid(Array.of(error));
});
return new ValidationBuilder(invalid);
}
}
}
Okay, so there's the Array<String>
, right? So then I looked into the decompiled .class for Validation
. It was gigantic, and also an interface...
public interface Validation<E, T> extends Value<T> {
static <E, T> Validation<E, T> valid(T value) {
return new Validation.Valid(value);
}
static <E, T> Validation<E, T> invalid(E error) {
Objects.requireNonNull(error, "error is null");
return new Validation.Invalid(error);
}
static <E, T> Validation<E, T> fromEither(Either<E, T> either) {
Objects.requireNonNull(either, "either is null");
return either.isRight() ? valid(either.get()) : invalid(either.getLeft());
}
static <E, T> Validation<List<E>, Seq<T>> sequence(Iterable<? extends Validation<List<E>, T>> values) {
Objects.requireNonNull(values, "values is null");
List<E> errors = List.empty();
List<T> list = List.empty();
Iterator var3 = values.iterator();
while(var3.hasNext()) {
Validation<List<E>, T> value = (Validation)var3.next();
if (value.isInvalid()) {
errors = errors.prependAll(((List)value.getError()).reverse());
} else if (errors.isEmpty()) {
list = list.prepend(value.get());
}
}
return errors.isEmpty() ? valid(list.reverse()) : invalid(errors.reverse());
}
static <E, T> Validation<E, T> narrow(Validation<? extends E, ? extends T> validation) {
return validation;
}
// ...
default boolean isEmpty() {
return this.isInvalid();
}
T get();
E getError();
default Either<E, T> toEither() {
return this.isValid() ? Either.right(this.get()) : Either.left(this.getError());
}
boolean equals(Object var1);
int hashCode();
String toString();
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action, "action is null");
if (this.isValid()) {
action.accept(this.get());
}
}
// ...
(Much omitted.) I feel I'm missing something going on here:
Validation<Array<String>, T> invalid = (Validation)this.validation.fold((errors) -> {
return Validation.invalid(errors.append(error));
}, (testObject) -> {
return Validation.invalid(Array.of(error));
});
(I'm coming from C++, and new to Java as well as newer features like lambdas.) Where is the data of (errors)
coming from, and how can I see it in the debugger's list of variables (or why can't I see them?)
Upvotes: 0
Views: 957
Reputation: 30273
Actually, it turned out I couldn't see the fields I was looking for because the validation I thought was being added, was not being added, so the underlying structure was based on something named Valid
rather than Invalid
. Once I correctly triggered the validation, I saw this:
Mockito was indeed mocking the adRequest
instance, but it had no bearing on the validation around this mocked instance.
Upvotes: 0
Reputation: 47875
The instance of ValidationBuilder
at play here is a cglib generated proxy. It has been created by Mockito so I'm guessing that you are debugging a test.
The Mockito proxy does not have the state you would normally expect to be in a ValidationBuilder
, instead it (sort of) has the state you 'give' it by setting expectations on it.
Upvotes: 1