Intent extra in Unit test Android Mockito

xkrw2x1b  于 2023-10-18  发布在  Android
关注(0)|答案(2)|浏览(139)

我试图验证是否向Intent添加了特定的额外内容,但在Android单元测试中,Intent始终为null。我有以下类需要测试:

public class TestClass extends SomeNotifier {
        private Intent mIntent = new Intent("testintent");

        public TestClassConstructor(Context context) {
            super(context);
        }

        @Override
        public void notifyChange() {
            mIntent.putExtra("Key one", 22);
            mIntent.putExtra("Key two", 23);
            mIntent.putExtra("Key three", 24);
            getContext().sendBroadcast(mIntent);
        }
    }

测试如下(我也尝试了mockIntent,但结果是一样的,额外的内容也是null):

@RunWith(MockitoJUnitRunner.class)
public class TestClassTest {

  @Mock
  Context mMockContext;

  @Test
  public void sendBroadcastTest() {

  ArgumentCaptor<Intent> argument = ArgumentCaptor.forClass(Intent.class);

  TestClass testClassNotifier = new TestClass (mMockContext);
  testClassNotifier.notifyChange();
  verify(mMockContext).sendBroadcast(argument.capture());

 Intent intent = argument.getValue();
 //THE INTENT IS NULL
 Assert.assertTrue(intent.hasExtra("Key one"));

    }
}

你有什么建议,我应该如何使这个测试工作?Thanks in advance

gab6jxml

gab6jxml1#

默认情况下,Intent和其他Android运行时类(如Context)仅在物理Android手机和模拟器上可用。对于本地单元测试,您将获得运行时的存根版本,其中Intent等。方法默认返回null。参见this question以获取解释。
这意味着您当前的测试正在验证Intent的存根版本,默认情况下,该版本将为所有方法调用返回null
有一些方法可以解决这个问题-您可以将测试转换为 Jmeter 化单元测试,这意味着您必须在真实的手持设备或模拟器上运行它。或者,您可以用您控制的类 Package Intent类。
也许最好的解决方案是使用像Robolectric这样的框架。这将为您提供重要Android类(如Intent)的工作测试替身(称为影子),用于在IDE中运行的本地单元测试。
一旦您仔细安装了Robolectric,您只需添加以下内容即可使您的测试工作:

@RunWith(RobolectricTestrunner.class)
public class TestClassTest {

顺便说一句,请确保您在Android上使用了Mockito的正确依赖项:

testCompile 'org.mockito:mockito-core:2.8.9'
androidTestCompile 'org.mockito:mockito-android:2.8.9'
ni65a41a

ni65a41a2#

您可以使用Mockk模拟intent

@Test
fun `Test`() {
    // Arrange
    val longValue = 1000L
    val enumValue = ModelEnum.MODEL1
    val intentMock = spyk<Intent>()
    every { intentMock.extras?.getLong("KEY_LONG_VALUE") } returns longValue
    every { intentMock.hasExtra(CheckoutRouter.RESULT_PAYMENT_TYPE) } returns true
    every { intentMock.getSerializableExtra("KEY_ENUM_VALUE") } returns enumValue

    // Action
    val a = A(intent = intentMock)
    val longValueResult = a.getLongValue()
    val enumValueResult =  a.getEnumValue()

    // Assert
    Assert.assertEquals(longValue, longValueResult)
    Assert.assertEquals(enumValue, enumValueResult)
}

class A (val intent: Intent){

    fun getLongValue():Long? {
        return intent.extras?.getLong("KEY_LONG_VALUE")
    }

    fun getEnumValue():ModelEnum? {
        return intent.getSerializableExtra("KEY_ENUM_VALUE") as? ModelEnum
    }
}

enum class ModelEnum{
    MODEL1,MODEL2
}

相关问题