Testen benutzerdefinierter Ansichten mit Robolectric
Ich versuche zum ausführen von unit-tests mit Robolectric 2.1.1 und ich kann es nicht aufpumpen benutzerdefinierte layouts (z.B. ViewPagerIndicator-Klassen).
Angenommen, dies ist mein layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="test"
android:id="@+id/test_test"/>
<com.viewpagerindicator.CirclePageIndicator
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
Betrachten Sie diese meine test-Klasse:
@RunWith(RobolectricTestRunner.class)
public class TestRoboActivityTest {
private TestRoboActivity mActivity;
@Before
public void setUp() throws Exception {
mActivity = Robolectric.buildActivity(TestRoboActivity.class).create().get();
}
@After
public void tearDown() throws Exception {
mActivity = null;
}
@Test
public void testSanity() throws Exception {
Assert.assertNotNull(mActivity);
}
}
Ausführung von "mvn clean test' - Ergebnisse im
Tests Fehler: testSanity(TestRoboActivityTest): XML-Datei .\res\layout\test.xml Zeile #-1 (sorry, noch nicht implementiert): Error inflating class com.viewpagerindicator.CirclePageIndicator
Cool, so scheint es, wie benutzerdefinierte Ansichten werden nicht unterstützt noch. Die überprüfung der Probe Robolectric Projekt auf Ihre website,
eine Lösung könnte sein, Blasen Sie das layout aus LayoutInflater:
@RunWith(RobolectricTestRunner.class)
public class TestRoboActivityTest {
private View mTestRoboActivityView;
@Before
public void setUp() throws Exception {
mTestRoboActivityView = LayoutInflater.from(new Activity()).inflate(R.layout.test, null);
}
@After
public void tearDown() throws Exception {
mTestRoboActivityView = null;
}
@Test
public void testSanity() throws Exception {
Assert.assertNotNull(mTestRoboActivityView);
}
}
sind die Ergebnisse in:
Tests Fehler: testSanity(TestRoboActivityTest): XML-Datei .\res\layout\test.xml Zeile #-1 (sorry, noch nicht implementiert): Error inflating class com.viewpagerindicator.CirclePageIndicator
Mein letzter Ausweg war, versucht die Schatten-Klassen:
@Implements(CirclePageIndicator.class)
public class CirclePageIndicatorShadow implements PageIndicator {
@Override
@Implementation
public void setViewPager(ViewPager view) {
//Stub
}
//etc.
}
und mit @Config(shadows = {CirclePageIndicatorShadow.class})
. Dies führte erneut zu
Tests Fehler: testSanity(TestRoboActivityTest): XML-Datei .\res\layout\test.xml Zeile #-1 (sorry, noch nicht implementiert): Error inflating class com.viewpagerindicator.CirclePageIndicator
Bearbeiten (Dezember 2014)
Bitte beachten Sie, dass die folgenden stracktrace Hinzugefügt wurde später von David Rabinowitz. Während Verwandte, es ist nicht das Problem, das ich konfrontiert war, zu der Zeit.
Hier ist der stack trace:
android.view.InflateException: XML file .\res\layout\activity_home.xml line #-1 (sorry, not yet implemented): Error inflating class com.test.custom.RobotoTextView
at android.view.LayoutInflater.createView(LayoutInflater.java:613)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:687)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:746)
at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
at org.robolectric.tester.android.view.RoboWindow.setContentView(RoboWindow.java:82)
at org.robolectric.shadows.ShadowActivity.setContentView(ShadowActivity.java:273)
at android.app.Activity.setContentView(Activity.java)
at com.example.testrobocustomfont.MainActivity.onCreate(MainActivity.java:12)
at com.example.testrobocustomfont.MainActivityTest.setUp(MainActivityTest.java:28)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:27)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:241)
at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:177)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
at android.view.LayoutInflater.$$robo$$LayoutInflater_1d1f_createView(LayoutInflater.java:587)
at android.view.LayoutInflater.createView(LayoutInflater.java)
at android.view.LayoutInflater.$$robo$$LayoutInflater_1d1f_createViewFromTag(LayoutInflater.java:687)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java)
at android.view.LayoutInflater.$$robo$$LayoutInflater_1d1f_rInflate(LayoutInflater.java:746)
at android.view.LayoutInflater.rInflate(LayoutInflater.java)
at android.view.LayoutInflater.$$robo$$LayoutInflater_1d1f_inflate(LayoutInflater.java:489)
at android.view.LayoutInflater.inflate(LayoutInflater.java)
at android.view.LayoutInflater.$$robo$$LayoutInflater_1d1f_inflate(LayoutInflater.java:396)
at android.view.LayoutInflater.inflate(LayoutInflater.java)
at android.view.LayoutInflater.$$robo$$LayoutInflater_1d1f_inflate(LayoutInflater.java:352)
at android.view.LayoutInflater.inflate(LayoutInflater.java)
at org.robolectric.tester.android.view.RoboWindow.setContentView(RoboWindow.java:82)
at org.robolectric.shadows.ShadowActivity.setContentView(ShadowActivity.java:273)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.robolectric.bytecode.ShadowWrangler$ShadowMethodPlan.run(ShadowWrangler.java:455)
at android.app.Activity.setContentView(Activity.java)
at com.example.testrobocustomfont.MainActivity.onCreate(MainActivity.java:12)
at com.example.testrobocustomfont.MainActivityTest.setUp(MainActivityTest.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
... 22 more
Caused by: java.lang.RuntimeException: error converting RobotoMedium.ttf using EnumConverter
at org.robolectric.shadows.Converter.convertAndFill(Converter.java:150)
at org.robolectric.shadows.Converter.convertAndFill(Converter.java:50)
at org.robolectric.shadows.ShadowResources.createTypedArray(ShadowResources.java:228)
at org.robolectric.shadows.ShadowResources.attrsToTypedArray(ShadowResources.java:203)
at org.robolectric.shadows.ShadowResources.access$000(ShadowResources.java:51)
at org.robolectric.shadows.ShadowResources$ShadowTheme.obtainStyledAttributes(ShadowResources.java:460)
at android.content.res.Resources$Theme.obtainStyledAttributes(Resources.java)
at android.widget.TextView.__constructor__(TextView.java:561)
at android.widget.TextView.<init>(TextView.java:447)
at android.widget.TextView.<init>(TextView.java:442)
at com.test.custom.RobotoTextView.<init>(RobotoTextView.java:16)
at android.view.LayoutInflater.createView(LayoutInflater.java:587)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:687)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:746)
at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
at org.robolectric.tester.android.view.RoboWindow.setContentView(RoboWindow.java:82)
at org.robolectric.shadows.ShadowActivity.setContentView(ShadowActivity.java:273)
at android.app.Activity.setContentView(Activity.java)
at com.example.testrobocustomfont.MainActivity.onCreate(MainActivity.java:12)
at com.example.testrobocustomfont.MainActivityTest.setUp(MainActivityTest.java:28)
... 22 more
Caused by: java.lang.RuntimeException: no value found for RobotoMedium.ttf
at org.robolectric.shadows.Converter$EnumOrFlagConverter.findValueFor(Converter.java:375)
at org.robolectric.shadows.Converter$EnumConverter.fillTypedValue(Converter.java:343)
at org.robolectric.shadows.Converter$EnumConverter.fillTypedValue(Converter.java:336)
at org.robolectric.shadows.Converter.convertAndFill(Converter.java:148)
at org.robolectric.shadows.Converter.convertAndFill(Converter.java:50)
at org.robolectric.shadows.ShadowResources.createTypedArray(ShadowResources.java:228)
at org.robolectric.shadows.ShadowResources.attrsToTypedArray(ShadowResources.java:203)
at org.robolectric.shadows.ShadowResources.access$000(ShadowResources.java:51)
at org.robolectric.shadows.ShadowResources$ShadowTheme.obtainStyledAttributes(ShadowResources.java:460)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.robolectric.bytecode.ShadowWrangler$ShadowMethodPlan.run(ShadowWrangler.java:455)
at android.content.res.Resources$Theme.obtainStyledAttributes(Resources.java)
at android.widget.TextView.$$robo$$TextView_347d___constructor__(TextView.java:561)
at android.widget.TextView.<init>(TextView.java:447)
at android.widget.TextView.<init>(TextView.java:442)
at com.test.custom.RobotoTextView.<init>(RobotoTextView.java:16)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
at android.view.LayoutInflater.$$robo$$LayoutInflater_1d1f_createView(LayoutInflater.java:587)
at android.view.LayoutInflater.createView(LayoutInflater.java)
at android.view.LayoutInflater.$$robo$$LayoutInflater_1d1f_createViewFromTag(LayoutInflater.java:687)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java)
at android.view.LayoutInflater.$$robo$$LayoutInflater_1d1f_rInflate(LayoutInflater.java:746)
at android.view.LayoutInflater.rInflate(LayoutInflater.java)
at android.view.LayoutInflater.$$robo$$LayoutInflater_1d1f_inflate(LayoutInflater.java:489)
at android.view.LayoutInflater.inflate(LayoutInflater.java)
at android.view.LayoutInflater.$$robo$$LayoutInflater_1d1f_inflate(LayoutInflater.java:396)
at android.view.LayoutInflater.inflate(LayoutInflater.java)
at android.view.LayoutInflater.$$robo$$LayoutInflater_1d1f_inflate(LayoutInflater.java:352)
at android.view.LayoutInflater.inflate(LayoutInflater.java)
at org.robolectric.tester.android.view.RoboWindow.setContentView(RoboWindow.java:82)
at org.robolectric.shadows.ShadowActivity.setContentView(ShadowActivity.java:273)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.robolectric.bytecode.ShadowWrangler$ShadowMethodPlan.run(ShadowWrangler.java:455)
at android.app.Activity.setContentView(Activity.java)
at com.example.testrobocustomfont.MainActivity.onCreate(MainActivity.java:12)
at com.example.testrobocustomfont.MainActivityTest.setUp(MainActivityTest.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
... 22 more
Könntet Ihr denn bitte zeigen Sie mich in die richtige Richtung? Ich bin aus Ideen heraus.
Danke.
- Kannst du einen vollständigen stack-trace?
- Verwenden Sie eine benutzerdefinierte schriftart oder einen benutzerdefinierten Ansicht verwendet eine benutzerdefinierte schriftart? Ich denke, @joecks ist auf dem richtigen Weg mit Ihrer Antwort. Android kann nicht Rendern von benutzerdefinierten Schriftarten in einer Vorschau (ie, wenn Sie die xml-Datei in Eclipse), und das gleiche problem kann auftreten hier. Wenn Sie den text anzeigen, versuchen das einwickeln der code ruft den Stil mit
if (!isInEditMode())
- Sind Sie in der Lage, um die benutzerdefinierte Ansicht in den layout-xml-grafische Vorschau?
- Ähnlich: Testen ViewPager (und CursorLoader) mit Robolectric
- Ich testen können benutzerdefinierte Ansichten. Vielleicht ist etwas falsch mit Ihre benutzerdefinierte Ansicht. Versuchen Sie, eine temporäre und sehr einfache benutzerdefinierte Ansicht (im Grunde nur verlängern-Taste oder textview). Stecken Sie dieses einfache, benutzerdefinierte Ansicht, wo Ihr die aktuelle Ansicht ist. Sehen Sie, wenn Sie immer noch Beschwerden darüber.
- Könnte der OP post seine/Ihre stack-trace in Ordnung, dass wir helfen könnten? Wenn man jemanden hat, der stack-trace nicht sehr hilfreich ist. Danke.
- Haben Sie keine Lösung gefunden dafür ? Ich bin mit der gleichen Art von Problem.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Problem:
Dieses Problem passiert, weil gradle vereint Projekt-Abhängigkeiten (ex:
compile project(':lib-custom')
) und externe Abhängigkeiten (ex:compile 'lib.package:name:1.1.0'
) auf unterschiedliche Weise. Nach Abhängigkeiten wurden zusammengeführt app hatR.java
- Datei, die alle Ressourcen-Felder (Farben, ids, drawables, ...). Aber generiertR.java
Datei sieht anders aus, nach der Zusammenführung teilmodule und externe Abhängigkeiten.Dieses problem existiert nur bei Projekten mit benutzerdefinierten Ansichten im teilmodule. Im Falle von externen Abhängigkeiten gibt es andere Probleme, die leicht behoben werden können. Lesen Sie über die Abhängigkeiten der Arten hier.
Für die Projekt-Abhängigkeiten Ergebnis
R.java
- Datei enthält alle Ressource-Identifier, aber Kennungen von Submodul nicht gleich zu Ihrer ursprünglichen integer-Bezeichner:Für externe Abhängigkeiten zusammengeführt
R.java
Datei nur ein merge-Ergebnis R.java Dateien von allen externen AbhängigkeitenLösung:
Ich gefunden habe zwei mögliche Lösungen:
Aber das ist noch nicht genug - Sie müssen hinzufügen von Verwandte-Element zu Projekt.Eigenschaften Datei auf Ihrem Haupt-sourceSet. Mehr info hier
Beispiel:
Können Sie überprüfen, diff für diese Lösung hier
Error inflating class
.Ich bevorzuge die erste Lösung, aber es ist nicht möglich, ändern manchmal-Projekt Abhängigkeit von externen.
Ich werde auch berichten über dieses Problem zu Robolectric-team.
P. S. ich habe Projekt auf github im Zusammenhang mit diesem Problem.
Ich Teste Ansichten in der gleichen Prüfung der Klasse mit der Tätigkeit, die Sie verwendet. In diesem Fall sage ich Robolectric zu geben, eine Instanz, die Aktivität und die bekomme ich auch eine Instanz von dem aufgeblähten Blick:
LE: ich benutze Robolectric 3.0, so bin ich nicht sicher, ob dies auf Sie zutrifft.
mTestRoboActivityView = LayoutInflater.from(new Activity()).inflate(R.layout.test, null);
In dieser Linie der code, den Sie verwenden 'new Activity ()" bedeutet Beispiel von neuen Aktivitäten, die nicht für Ihre aktuelle Tätigkeit.
Sie können dieses Problem beheben, indem die übergabe-Instanz auf die aktuelle Aktivität.
Verwenden Sie diese
Ich bin nicht sicher, ob obige code funktioniert einwandfrei, aber die Verwendung für die Referenz-Instanz des aktuellen Aktivität.
Finden es kann Ihnen helfen.
Kann man nicht aufblasen, Blick in Roboelectric, da es nicht den kompletten android-framework, sondern verhöhnt alle Android-API.
Sollten Sie nicht verwenden roboelectric zu testen eigentlichen view-display-Verhalten.
Es ist zu sein verwendet für die unit-tests und nur um zu testen Sie Ihre business-Logik und nicht in Ansicht zeichnen/display usw.. Das zu erreichen, können Sie programmgesteuert erstellen Sie Objekte anzeigen und mock, bestimmte Teile, die das android-system (so etwas wie Mockito oder Powermock).
zB der simple-view-Prüfung in roboelectic:
Auch wenn Sie testen möchten, Rendern, wie Ihr Blick sieht oder macht etc verwenden, sollten Sie das funktionale testing-frameworks wie Espresso oder Robotium, die auf einem tatsächlichen Gerät.