btn.performClick()无法模拟对象,但Activity调用该函数是可以的

时间:2016-05-13 02:38:23

标签: android unit-testing mockito robolectric activityunittestcase

我尝试使用Mockito测试按钮功能。代码包括Layout / SampleActivity / UnitTest主要内容:

布局文件定义:

android:text="testbtnmock"
android:id="@+id/btn_testbtnmock"
android:onClick="testBtnMock"

SampleActivity文件定义

public void testBtnMock(View view) {
    System.out.println("value:"+getInt());
}

public int getInt(){
    return 0;
}

UnitTest文件定义

@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class)
public class SampleActivityTest {
  private SampleActivity sampleActivity;
  private Button testBtnMock;
  @Before
  public void setUp() {
    ShadowLog.stream = System.out;
  }
  @Test
  public void testBtnMock() {
    sampleActivity = Robolectric.setupActivity(SampleActivity.class);
    SampleActivity spySampleActivity = spy(sampleActivity);
    when(spySampleActivity.getInt()).thenReturn(100);
    //spySampleActivity.testBtnMock(mock(View.class));  //it is working , print 100
    testBtnMock = (Button) sampleActivity.findViewById(R.id.btn_testbtnmock);
    testBtnMock.performClick(); //it is not work , print 0 ,mock invalid
  }
}

我的问题是:

  1. 为什么使用spySampleActivity.testBtnMock(mock(View.class));来触发testBtnMock(View v)的功能。它工作并打印100。
  2. 但使​​用testBtnMock.performClick();无法正常工作并打印0为什么?如何解决?

1 个答案:

答案 0 :(得分:0)

这很容易解释。

XML属性将用于通过反射(How does the android Xml attribute android:onClick="..." work behind the scenes?)调用方法。

因此,通过一些简化,将使用按钮的上下文,并通过反射调用方法。按钮在通货膨胀期间获得背景,它是不间谍活动的参考。这就是你的测试中调用真实方法的原因。

通过对间谍活动的引用来调用方法时,它可以正常工作。

如何解决:

  1. 提取一个负责提供整数
  2. 的类
  3. 模拟并注入测试
  4. 类似的东西:

    public class IntegerProvider {
      public int getInt(){
         return 0;
      }  
    }
    
    public class SampleActivity {
       IntegerProvider intProvider;
    
       public void testBtnMock(View view) {
         System.out.println("value:" + intProvider.getInt());
       }
    }
    
    @Test
    public void testBtnMock() {
        sampleActivity = Robolectric.setupActivity(SampleActivity.class);
        IntegerProvider providerMock = mock(IntegerProvider.class);
        when(providerMock.getInt()).thenReturn(100);
        sampleActivity.intProvider = providerMock;
    
        testBtnMock = (Button) sampleActivity.findViewById(R.id.btn_testbtnmock);
        testBtnMock.performClick();
    }