如何在Robolectric中为自定义视图配置RoboAttributeSet?

时间:2014-07-28 16:10:50

标签: java android xml attr robolectric

我正在使用自己的属性测试(工作)复合控件(也称为自定义视图)并尝试使用RoboAttributeSet来配置视图的属性。我还没有找到关于此功能的全面示例或文档,以及在使用构造函数时我的属性创建使用的值。我确定它很容易解决,但我无法找到它。

我已经审核了这些问题:RoboAttributeSetCustom view inflation errorShadowing custom views ......以及其他互联网无济于事。

注意:我的完整软件包名称为:com.colabug.local.food

注意:我使用的文件名不是attrs.xml,如Android教程中所述。

CoverViewTest.java

public class CoverViewTest
{
    private Activity activity;
    private CoverView coverView;

    // Data
    private Delicacy data;

    // UI
    private RatingBar ratingBar;

    @Before
    public void setUp() throws Exception
    {
        activity = createActivity();
        coverView = getCoverView( activity, null );
        data = createDummyData( false, 2, false );
        coverView.setData( data );

        ratingBar = (RatingBar) coverView.findViewById( R.id.cover_view_rating_bar );
    }

    private CoverView getCoverView( Activity activity,
                                    RoboAttributeSet attributeSet )
    {
        CoverView view;
        view = new CoverView(Robolectric.application.getApplicationContext(), attributeSet);

//        view = (CoverView) LayoutInflater.from( activity )
//                                         .inflate( R.layout.cover_view,
//                                                   new CoverView( activity ),
//                                                   true );

        return view;
    }

    @Test
    public void showRatingBarAttribute_shouldShowRatingBar() throws Exception
    {
        ArrayList<Attribute> attributes = new ArrayList<Attribute>();
        attributes.add( new Attribute( "com.colabug.local.food:cover_attrs/showRatingBar", String.valueOf( true ), "com.colabug.local.food") );
        RoboAttributeSet attributeSet = new RoboAttributeSet( attributes,
                                                              Robolectric.application.getResources(),
                                                              CoverView.class );

        CoverView view = getCoverView( activity, attributeSet );
        view.setData( createDummyData( false, 2, false ) );
        assertViewIsVisible( view.findViewById( R.id.cover_view_rating_bar ) );
    }
}

错误

java.lang.IllegalStateException: "com.colabug.local.food:cover_attrs/showRatingBar" unexpected
    at org.robolectric.res.Attribute.<init>(Attribute.java:90)
    at org.robolectric.res.Attribute.<init>(Attribute.java:86)
    at com.colabug.local.food.views.CoverViewTest.setShowRatingBar_shouldShowRatingBar(CoverViewTest.java:140)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    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.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
    at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:250)
    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.junit.runners.Suite.runChild(Suite.java:128)
    at org.junit.runners.Suite.runChild(Suite.java:24)
    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.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:77)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:195)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:63)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

RES /值/ cover_attrs.xml

<?xml version="1.0" encoding="utf-8"?>

<resources>
   <declare-styleable name="CoverView">
       <attr name="showRatingBar" format="boolean" />
   </declare-styleable>
</resources>

CoverView.java

public class CoverView extends RelativeLayout
{
    private BaseModel data;

    // UI
    private LayoutInflater inflater;
    private RatingBar      ratingBar;

    // Attributes
    private boolean showRatingBar = false;

    public CoverView( Context context )
    {
        super( context );
        inflater = LayoutInflater.from( context );
        initViews();
    }

    public CoverView( Context context, AttributeSet attrs )
    {
        super( context, attrs );

        getStyledAttributes( context, attrs );
        inflater = LayoutInflater.from( context );
        initViews();
    }

    public CoverView( Context context, AttributeSet attrs, int defStyle )
    {
        super( context, attrs, defStyle );

        getStyledAttributes( context, attrs );
        inflater = LayoutInflater.from( context );
        initViews();
    }

    public static CoverView inflate( ViewGroup parent, int layoutId )
    {
        return (CoverView) LayoutInflater.from( parent.getContext() )
                                         .inflate( layoutId, parent, false );
    }

    private void initViews()
    {
        inflater.inflate( R.layout.cover_view, this );
        ratingBar = (RatingBar) findViewById( R.id.cover_view_rating_bar );
    }

    private void getStyledAttributes( Context context, AttributeSet attrs )
    {
        TypedArray attributes = getAttributeArray( context, attrs );

        try
        {
            showRatingBar = attributes.getBoolean( R.styleable.CoverView_showRatingBar, false );
        }
        finally
        {
            attributes.recycle();
        }
    }

    private TypedArray getAttributeArray( Context context, AttributeSet attrs )
    {
        return context.getTheme().obtainStyledAttributes( attrs, R.styleable.CoverView, 0, 0 );
    }

    public void setData( BaseModel data )
    {
        this.data = data;

        configureRatingBar();

        redrawView();
    }

    private void redrawView()
    {
        invalidate();
        requestLayout();
    }

    private void configureRatingBar()
    {
        if ( showRatingBar )
        {
            ratingBar.setVisibility( VISIBLE );
        }
        else
        {
            ratingBar.setVisibility( GONE );
        }
    }

    public boolean hasRatingBar()
    {
        return showRatingBar;
    }

    public void setShowRatingBar( boolean showRatingBar )
    {
        this.showRatingBar = showRatingBar;
        redrawView();
    }
}

RES /布局/ cover_view.xml

<merge
    xmlns:android="http://schemas.android.com/apk/res/android"
    style="@style/MatchWidth">

    <!--Location image-->
    <ImageView
        android:id="@+id/cover_view_image"
        android:adjustViewBounds="true"
        android:src="@drawable/philly"
        android:contentDescription="@string/LOCATION_CONTENT_DESC"
        style="@style/MatchWidth"/>

...    

        <!--Rating bar-->
        <RatingBar
            android:id="@+id/cover_view_rating_bar"
            style="@style/RatingBar"/>
</merge>

2 个答案:

答案 0 :(得分:3)

对于那些仍然想知道如何在版本3中配置的人:查看Roboelectric的样本。找我这么久就找到了。

https://github.com/robolectric/robolectric/blob/490e5fcb7165bec9ef2ddc1c937af790806bb13d/robolectric/src/test/java/org/robolectric/shadows/ViewStubTest.java#L59

答案 1 :(得分:0)

尽管命名文件cover_attrs.xml,但在那里声明的资源类型仍然是attr,看起来这就是Robolectric在抛出异常时试图强制实施的内容({{3} })。

您可以尝试将attributes.add来电中的属性更改为"com.colabug.local.food:attr/showRatingBar"并查看其是否有效吗?