5

używając normalnego android.app.AlertDialog współpracuje z ShadowAlertDialog.getLatestAlertDialog(), ale jeśli używasz biblioteki support android.support.v7.app.AlertDialog, to wyjątek dzieje:Robolectric InflateException przy użyciu biblioteki wsparcie v7 AlertDialog

android.view.InflateException: XML file app/build/intermediates/res/qa/debug/layout/abc_alert_dialog_material.xml line #-1 (sorry, not yet implemented): Error inflating class android.support.v7.internal.widget.DialogTitle 
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:713) 
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:755) 
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:758) 
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:758) 
    at android.view.LayoutInflater.inflate(LayoutInflater.java:492) 
    at uk.co.chrisjenx.calligraphy.CalligraphyLayoutInflater.inflate(CalligraphyLayoutInflater.java:60) 
    at android.view.LayoutInflater.inflate(LayoutInflater.java:397) 
    at android.view.LayoutInflater.inflate(LayoutInflater.java:353) 
    at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:249) 
    at android.support.v7.app.AppCompatDialog.setContentView(AppCompatDialog.java:75) 
    at android.support.v7.app.AlertController.installContent(AlertController.java:216) 
    at android.support.v7.app.AlertDialog.onCreate(AlertDialog.java:240) 
    at android.app.Dialog.dispatchOnCreate(Dialog.java:361) 
    at android.app.Dialog.show(Dialog.java:262) 
    at org.robolectric.shadows.ShadowDialog.show(ShadowDialog.java:65) 
    at android.app.Dialog.show(Dialog.java) 
<snip> 
Caused by: java.lang.StringIndexOutOfBoundsException: String index out of range: -9 
    at java.lang.String.substring(String.java:1955) 
    at org.robolectric.res.ResName.qualifyResName(ResName.java:51) 
    at org.robolectric.res.Attribute.getStyleReference(Attribute.java:147) 
    at org.robolectric.res.builder.XmlFileBuilder$XmlResourceParserImpl.getResourceId(XmlFileBuilder.java:789) 

Jest to znany problem, ale co najlepsze sposób obejścia go?
https://github.com/robolectric/robolectric/issues/1736

Odpowiedz

4

używać statycznego narzędzia do budowania moje AlertDialog obiektów i zbudować android.app.AlertDialog jedno kiedy wykryje Robolectric na ścieżce klasy. Oto mój kod:

private static Boolean isRobolectricTest = null; 

/** 
* Determines if we are running inside of Robolectric or not. 
*/ 
public static boolean isARobolectricUnitTest() { 
    if (isRobolectricTest == null) { 
     try { 
      Class.forName("org.robolectric.Robolectric"); 
      isRobolectricTest = true; 
     } catch (ClassNotFoundException e) { 
      isRobolectricTest = false; 
     } 
    } 
    return isRobolectricTest; 
} 

/** 
* This utility helps us to workaround a Robolectric issue that causes our unit tests to fail 
* when an Activity/Fragment creates an AlertDialog using the v7 support library. The 
* workaround is to use the normal android.app.AlertDialog when running Robolectric tests. 
* 
* The Robolectric bug is: https://github.com/robolectric/robolectric/issues/1736 
* android.view.InflateException: XML file app/build/intermediates/res/qa/debug/layout/abc_alert_dialog_material.xml line #-1 (sorry, not yet implemented): Error inflating class android.support.v7.internal.widget.DialogTitle 
*/ 
public static DialogInterface createAndShowDialog(Context context, 
                @StringRes int titleResId, 
                String message, 
                @StringRes int negativeTextResId, 
                DialogInterface.OnClickListener negativeClickListener, 
                @StringRes int neutralTextResId, 
                DialogInterface.OnClickListener neutralClickListener, 
                @StringRes int positiveTextResId, 
                DialogInterface.OnClickListener positiveClickListener, 
                boolean cancelable) { 
    if (isARobolectricUnitTest()) { 
     return UiUtils.createDialog(context, titleResId, message, negativeTextResId, negativeClickListener, neutralTextResId, neutralClickListener, positiveTextResId, positiveClickListener, cancelable); 
    } else { 
     return UiUtils.createDialogSupportV7(context, titleResId, message, negativeTextResId, negativeClickListener, neutralTextResId, neutralClickListener, positiveTextResId, positiveClickListener, cancelable); 
    } 
} 

private static android.app.AlertDialog createDialog(Context context, 
                @StringRes int titleResId, 
                String message, 
                @StringRes int negativeTextResId, 
                DialogInterface.OnClickListener negativeClickListener, 
                @StringRes int neutralTextResId, 
                DialogInterface.OnClickListener neutralClickListener, 
                @StringRes int positiveTextResId, 
                DialogInterface.OnClickListener positiveClickListener, 
                boolean cancelable) { 
    android.app.AlertDialog.Builder builder = new android.app.AlertDialog.Builder(context); 
    builder.setTitle(titleResId); 
    builder.setMessage(message); 
    builder.setNegativeButton(negativeTextResId, negativeClickListener); 

    if ((neutralTextResId != -1) && (neutralClickListener != null)) { 
     builder.setNeutralButton(neutralTextResId, neutralClickListener); 
    } 

    builder.setPositiveButton(positiveTextResId, positiveClickListener); 
    builder.setCancelable(cancelable); 

    android.app.AlertDialog alertDialog = builder.create(); 
    alertDialog.show(); 

    return alertDialog; 
} 

private static android.support.v7.app.AlertDialog createDialogSupportV7(Context context, 
                     @StringRes int titleResId, 
                     String message, 
                     @StringRes int negativeTextResId, 
                     DialogInterface.OnClickListener negativeClickListener, 
                     @StringRes int neutralTextResId, 
                     DialogInterface.OnClickListener neutralClickListener, 
                     @StringRes int positiveTextResId, 
                     DialogInterface.OnClickListener positiveClickListener, 
                     boolean cancelable) { 
    android.support.v7.app.AlertDialog.Builder builder = new android.support.v7.app.AlertDialog.Builder(context); 
    builder.setTitle(titleResId); 
    builder.setMessage(message); 
    builder.setNegativeButton(negativeTextResId, negativeClickListener); 

    if ((neutralTextResId != -1) && (neutralClickListener != null)) { 
     builder.setNeutralButton(neutralTextResId, neutralClickListener); 
    } 

    builder.setPositiveButton(positiveTextResId, positiveClickListener); 
    builder.setCancelable(cancelable); 

    android.support.v7.app.AlertDialog alertDialog = builder.create(); 
    alertDialog.show(); 

    return alertDialog; 
} 

To nie jest idealne, ale spełnia swoje zadanie, i to jest łatwe do usunięcia hack później, gdy problem Robolectric jest stała.

Powiązane problemy