projectlombok / lombok

Very spicy additions to the Java programming language.
https://projectlombok.org/
Other
12.79k stars 2.37k forks source link

@Delegate - as a way to mix-in a JUnit test. #1356

Open wheredevel opened 7 years ago

wheredevel commented 7 years ago

Hi, guys!

I'm mixing-in a "template" test into an "origin" test. Something like:

public interface TestSomething {
  void testSomething() throws Exception;

  @Builder
  public static final class Mixin {
    public void testSomething() throws Exception {
      // some actual test here
    }
  }
}

public class MyTest {
  @Delegate
  private TestSomething testSomething = TestSomething.Mixin.builder().build();
}

(Note: I omitted a way I pass MyTest context to the Mixin - it's an important part, but irrelevant to the issue subject.)

So, the question is:
How do I make JUnit discover the testSomething() of the origin, generated by @Delegate, as a test - like it was annotated with @Test ?

wheredevel commented 7 years ago

So, guys, how hard is it to allow @Test annotation near the @Delegate one?:

public class MyTest {
  @Delegate
  @Test 
  private TestSomething testSomething = TestSomething.Mixin.builder().build();
}

I guess, adding an onMethod to @Delegate is a dream come true:

public class MyTest {
  @Delegate(onMethod=@__({@Test}))
  private TestSomething testSomething = TestSomething.Mixin.builder().build();
}
wheredevel commented 7 years ago

Here's a cross-post at JUnit issue tracker: https://github.com/junit-team/junit4/issues/1457

forketyfork commented 4 years ago

I'm not acquainted with patterns "template"/"origin"/"mixin" in the context of unit testing, maybe if you could point to some articles or books that describe this approach, it would be easier for me to understand the problem you're solving.

As I understand it, the idea is to mix-in some common set of test methods into multiple test classes, while being able to provide different setup in each case.

I wouldn't advice to enrich the experimental @Delegate annotation with even more experimental onMethod property, as the result would be very hard to control. It might happen that some generated methods would receive the @Test annotation without intention.

As adviced in junit-team/junit4#1457, you could use BlockJUnit4ClassRunner to discover generated methods in JUnit 4. In JUnit 5, you could use DiscoverySelectors.

Also, in JUnit 5, you can annotate default methods of interfaces with the @Test annotation, and then use those interfaces as mixins for a concrete test class, as described in the documentation. This would be a nice alternative to using Lombok's @Delegate annotation.

wheredevel commented 4 years ago

@forketyfork , I think you understood the basic idea.
I have multiple "template" test implementations. They implement "generic" test flow, including asserts.
I want to mix-in some of those tests into "concrete" test class.
And, possibly, the "template" flow will use data from the "concrete" test class - for example, "concrete" test might be parameterized.