Matching @InjectProp
For help with setting up the test environment, see the Getting Started page.
Before learning about @InectProp
matching, it's recommended you become familiar with sub-component testing.
Testing Injected Propsβ
@InjectProp
earmarks props to be provided by the client's dependency injection framework. Components that have injected props can be tested using a @TestSpec
and the prop-matching APIs.
Consider the following LayoutSpec:
@LayoutSpec
class MyInjectPropSpec {
@OnCreateLayout
static Component onCreateLayout(
ComponentContext c,
@Prop String normalProp,
@InjectProp UserController injectedProp,
@InjectProp ProfilePictureComponent profilePicture) {
// ...
}
}
To test using injected props, take the following steps:
- Create a
@TestSpec
for MyInjectPropSpec:
@TestSpec(MyInjectPropSpec.class)
public interface TestMyInjectPropSpec {}
- Add
@RunWith(LithoTestRunner.class)
to the top of the test class. - Add a JUnit
@Rule
LithoViewRule
. - Add a check to ensure that tests are run in debug mode.
ComponentsConfiguration.IS_INTERNAL_BUILD
must be true.
The test class should look like the following:
@RunWith(LithoTestRunner.class)
public class InjectPropMatcherGenerationTest {
public final @Rule LithoViewRule mLithoViewRule = new LithoViewRule();
@Before
public void assumeInDebugMode() {
assumeThat(
"These tests can only be run in debug mode.",
ComponentsConfiguration.IS_INTERNAL_BUILD, is(true)
);
}
}
- Set the value of the injected props before evaluating any assertions:
@Test
public void whenMyInjectPropComponentIsRendered_shouldUseProvidedInjectProps() {
final ComponentContext c = mLithoViewRule.getContext();
final MyInjectProp component = MyInjectProp.create(c)
.normalProp("normal string")
.build();
// Set the injected prop values.
component.injectedString = "injected string";
component.injectedKettle = new Kettle(92f);
final Condition<InspectableComponent> matcher =
TestMyInjectProp.matcher(c)
.normalString("normal string")
.injectedString("injected string")
.injectedKettle(new CustomTypeSafeMatcher<MyInjectPropSpec.Kettle>("matches temperature") {
@Override
protected boolean matchesSafely(MyInjectPropSpec.Kettle item) {
return Math.abs(item.temperatureCelsius - 92f) < 0.1;
}
})
.build();
assertThat(c, component).has(deepSubComponentWith(c, matcher));
}
The above example shows how tests written for injected props are almost the same as normal props.
The Kettle
object is instantiated with a temperature, which is verified using a custom matcher.
Testing Injected Componentsβ
Components can also be @InjectProp
s, as shown in the following LayoutSpec:
@LayoutSpec
class MyInjectPropSpec {
@OnCreateLayout
static Component onCreateLayout(
ComponentContext c,
@InjectProp Text injectedComponent) {
return Column.create(c).child(injectedComponent).build();
}
}
Assert if MyInjectProp is mounted with the injected Text component:
@Test
public void whenMyInjectPropComponentIsRendered_shouldUseProvidedInjectedComponent() {
final ComponentContext c = mLithoViewRule.getContext();
final MyInjectProp component = MyInjectProp.create(c).build();
component.injectedComponent = Text.create(c).text("injected text").build();
final Condition<InspectableComponent> matcher =
TestMyInjectProp.matcher(c)
.injectedComponent(TestText.matcher(c).text("injected text").build())
.build();
assertThat(c, component).has(deepSubComponentWith(c, matcher));
}