gpt4 book ai didi

android - 如何在 BroadcastReceiver 中测试对 PendingIntent.getBroadcast(...) 的静态调用

转载 作者:搜寻专家 更新时间:2023-11-01 08:54:29 26 4
gpt4 key购买 nike

我真的迷失在这个问题上。我确实构建了以下 BroadcastReceiver

package ch.pas.smslistenerservice.receiver;

import ch.pas.smslistenerservice.service.SMSListenerService;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class Resend extends BroadcastReceiver {
private static String logTag = "ch.pas.smslistenerservice.resend";

@Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) { return; }

Log.i(logTag, "Resend received");

PendingIntent pIntent = getPendingIntent(context);
if(pIntent != null) {
Log.d(logTag, "Canceling intent");
pIntent.cancel();
}

Log.d(logTag, "Starting service...");
Intent serviceIntent = new Intent(context, SMSListenerService.class);
serviceIntent.putExtra(SMSListenerService.EXTRA_TYPE, SMSListenerService.TYPE_RESEND);
context.startService(serviceIntent);
}

protected PendingIntent getPendingIntent(Context context) {
return PendingIntent.getBroadcast(context, 0,
new Intent("ch.pas.smslistenerservice.RESEND"),
PendingIntent.FLAG_NO_CREATE);
}
}

我尝试测试 if 语句,我很想测试 PendingIntent 对象是否收到取消消息。

if(pIntent != null) { 
Log.d(logTag, "Canceling intent");
pIntent.cancel();
}

我尝试的是:

  1. 分解出检索待定 Intent 的方法,然后使用 mockito 模拟返回的 PendingIntent。这没有成功,因为 Mockito 无法模拟最终类(如 PendingIntent)。
  2. 使用 PowerMock 模拟静态调用 PendingIntent.getBroadcast(...) 但这没有成功,因为 PowerMock 不能在 Android 上运行,如果我在 JVM 上运行这个测试,我会得到一个带有“Stub!”的 RuntimeException。因为我正在扩展仅适用于 Android 的 BroadcastReceiver。

我知道在那种情况下测试它没有太大意义,因为在 if 语句中没有太多逻辑要测试,但如果有更多怎么办?

最佳答案

通过结合使用 PowerMock、Mockito 和 Robolectric(<= 这是缺少的变量)解决了这个问题。使用 Robolectric 来隐藏(模拟)对 PendingIntent.getBroadcast(...) 的静态调用并注入(inject)模拟的 PendingIntent。

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;

import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

import org.powermock.api.mockito.PowerMockito;
import org.robolectric.*;
import org.robolectric.annotation.Config;

import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;

import ch.pas.smslistenerservice.receiver.Resend;
import ch.pas.smslistenerservice.service.SMSListenerService;

@Config(shadows=CustomShadowPendingIntent.class)
@RunWith(RobolectricTestRunner.class)
public class ResendTest {
Resend receiver;
Context context;
PendingIntent pendingIntent;

@Before
public void before() {
context = Mockito.mock(Context.class);
pendingIntent = PowerMockito.mock(PendingIntent.class);
receiver = new Resend();
}

@Test
public void testStartServiceWithoutExistingPendingIntent() {
CustomShadowPendingIntent.setPendingIntent(null);

Intent intent = new Intent("ch.pas.smslistenerservice.RESEND");
receiver.onReceive(context, intent);

ArgumentCaptor<Intent> argument = ArgumentCaptor.forClass(Intent.class);
verify(context).startService(argument.capture());
Intent capturedIntent = argument.getValue();
assertFalse(-1 == capturedIntent.getIntExtra(SMSListenerService.EXTRA_TYPE, -1));
assertEquals(SMSListenerService.TYPE_RESEND,
capturedIntent.getIntExtra(SMSListenerService.EXTRA_TYPE, -1));
}

@Test
public void testStartServiceWithExistingPendingIntent() {
CustomShadowPendingIntent.setPendingIntent(pendingIntent);

Intent intent = new Intent("ch.pas.smslistenerservice.RESEND");
receiver.onReceive(context, intent);

verify(pendingIntent, times(1)).cancel();

ArgumentCaptor<Intent> argument = ArgumentCaptor.forClass(Intent.class);
verify(context).startService(argument.capture());
Intent capturedIntent = argument.getValue();
assertFalse(-1 == capturedIntent.getIntExtra(SMSListenerService.EXTRA_TYPE, -1));
assertEquals(SMSListenerService.TYPE_RESEND,
capturedIntent.getIntExtra(SMSListenerService.EXTRA_TYPE, -1));
}
}

还有阴影的 PendingIntent:

import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;

import android.app.PendingIntent;

@Implements(PendingIntent.class)
public class CustomShadowPendingIntent
extends org.robolectric.shadows.ShadowPendingIntent {
private static PendingIntent pendingIntentMock;

public static void setPendingIntent(PendingIntent intent) {
pendingIntentMock = intent;
}

@Implementation
public static PendingIntent getBroadcast(android.content.Context context,
int requestCode, android.content.Intent intent, int flags) {
return pendingIntentMock;
}
}

关于android - 如何在 BroadcastReceiver 中测试对 PendingIntent.getBroadcast(...) 的静态调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20020109/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com