0

I often find myself wanting to copy a living java object into my tests (in the source code). I doubt this is generally doable, but perhaps a asJavaSourceCode() method could be generated for all @AutoValue objects?

Here is some code to demonstrate what I want.

import com.google.auto.value.AutoValue;


@AutoValue
public abstract class Person {

    public abstract String name();

    public abstract Integer age();

    public static Person create(String name, Integer age) {
        return new AutoValue_Person(name, age);
    }

    public String asJavaSourceCode() {
        // Can this code be automatically generated?
        return "Person.create(\"" + name() + "\"," + age() + ")";
    }

    public static void main(String[] args) {
        System.out.println(Person.create("Jordan", 29));
        System.out.println(Person.create("Jordan", 29).asJavaSourceCode());
    }
}

When running this I get.

Person{name=Jordan, age=29}
Person.create("Jordan",29)

I would consider any of these a valid answer to this question:

  • "Yes, here's a library link"
  • "No, it doesn't exist yet"
  • "Somebody else did something similar."
  • "That is bad practice, don't do it, see Effective Java Book Item XYZ"
Tarrasch
  • 10,199
  • 6
  • 41
  • 57

1 Answers1

1

I think you can write a general-purpose asJavaSourceCode() using Java reflection. Start with this.getClass() which returns a java.lang.Class object. Get the class name with method getName(), getCanonicalName() or getSimpleName(). Get the class's Field descriptions with getFields(). Each gives you a field name and its types, and methods to get its current value.

Since you're using @AutoValue you can assume a create() method on your class (which you can also discover with reflection), but I'm not sure you can reliably discover the order of the parameters to this method, because reflection Method will give you the parameter types in the correct order, but not their names. If @AutoValue doesn't order them deterministically, in a way you can reproduce when discovering the fields with reflection, then using an @AutoValue builder instead of create() will allow you to write source that sets the fields by name.

asynchronos
  • 583
  • 2
  • 14