Andrew Cheong
Andrew Cheong

Reputation: 30273

How can I look into this variable in IntelliJ's debugger?

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:

enter image description here

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

Answers (2)

Andrew Cheong
Andrew Cheong

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:

enter image description here

Mockito was indeed mocking the adRequest instance, but it had no bearing on the validation around this mocked instance.

Upvotes: 0

glytching
glytching

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

Related Questions