View Javadoc

1   package com.atlassian.webdriver.testing.rule;
2   
3   import com.atlassian.pageobjects.TestedProduct;
4   import com.google.common.base.Supplier;
5   import org.junit.rules.TestRule;
6   
7   import static com.atlassian.pageobjects.TestedProductFactory.fromFactory;
8   import static com.google.common.base.Suppliers.memoize;
9   
10  /**
11   * <p/>
12   * Static factory for a set of JUnit4-compatible injection rules.
13   *
14   * <p/>
15   * Similar to {@link TestedProductRule}, but more powerful, this set of rules allows for injection of components
16   * living in the context of a tested product or its associated page binder, into test classes and objects.
17   *
18   * <p/>
19   * The product, or its page binder, MUST implement the {@link com.atlassian.pageobjects.inject.InjectionContext}
20   * interface, otherwise no injection will be performed.
21   *
22   * <p/>
23   * To achieve both static and member injection (which also implies that a single tested product instance will
24   * be associated with test class, rather than each test object), combine {@link org.junit.ClassRule}
25   * and @{@link org.junit.Rule} in the following pattern:
26   *
27   * <pre>
28   *     &#064;ClassRule
29   *     public static TestRule myProductStaticInjectionRule = InjectionRules.forTestClass(MyProduct.class);
30   *
31   *     &#064;Rule
32   *     public TestRule myProductMemberInjectionRule = InjectionRules.forTestInContext(this);
33   *
34   *
35   *     // (fields that will get injected)
36   *     &#064;Inject
37   *     private static MyProduct myProduct; // per class
38   *
39   *     &#064;Inject
40   *     private PageBinder myPageBinder; // per test object instance, but the same binder instance
41   *
42   *     // etc...
43   * </pre>
44   *
45   * <p/>
46   * You may also choose to use the class rule only, if all you need is static members injection.
47   *
48   * <p/>
49   * If you prefer having a new tested product created for each test method, use the following factory in conjunction with
50   * {@link org.junit.Rule} annotation:
51   *<pre>
52   *     &#064;Rule
53   *     public TestRule myProductMemberInjectionRule = TestInjectionRule.forTest(this, MyProduct.class);
54   *
55   *      // (fields that will get injected)
56   *
57   *     &#064;Inject
58   *     private PageBinder myPageBinder; // per test object instance, but the same binder instance
59   *
60   *     // etc...
61   * </pre>
62   *
63   * <p/>
64   * An example test class
65   *
66   * <p/>
67   * IMPORTANT: the methods {@link #forTestInContext(Object)} and {@link #forTest(Object, Class)} provide different
68   * implementations of rules, the first of which depends on a class rule created via {@link #forTestClass(Class)}
69   * being present on the test class. Please choose one of the above options for your test (or base test) depending whether
70   * you need just static or just member injection, or both.
71   *
72   * @since 2.1
73   */
74  public final class InjectionRules
75  {
76  
77      private InjectionRules()
78      {
79          throw new AssertionError("Don't instantiate me");
80      }
81  
82      public static <T extends TestedProduct<?>> InjectingTestRule forTestClass(Class<T> productClass)
83      {
84          return new ClassInjectionRule<T>(memoize(fromFactory(productClass)));
85      }
86  
87      public static <T extends TestedProduct<?>> InjectingTestRule forTestClass(Supplier<T> productSupplier)
88      {
89          return new ClassInjectionRule<T>(productSupplier);
90      }
91  
92      public static TestRule forTestInContext(Object testInstance)
93      {
94          return new InstanceInjectionRules.InstanceCollaboratingInjectionRule(testInstance);
95      }
96  
97      public static <T extends TestedProduct<?>> TestRule forTest(Object testInstance, Class<T> testedProductClass)
98      {
99          return new InstanceInjectionRules.InstanceStandaloneInjectionRule<T>(testInstance, memoize(fromFactory(testedProductClass)));
100     }
101 
102     public static <T extends TestedProduct<?>> TestRule forTest(Object testInstance, Supplier<T> productSupplier)
103     {
104         return new InstanceInjectionRules.InstanceStandaloneInjectionRule<T>(testInstance, productSupplier);
105     }
106 }