如何为 Firebase 通知编写单元测试



我创建了以下类来接收Firebase消息并创建通知。我已经通过向应用程序发送 firebase 消息对其进行了测试,它运行良好。但是,我需要编写单元测试来测试此功能。但是我为它编写的 2 个单元测试失败了。 onMessageReceived()接收RemoteMessage对象中的数据。然后,它找到键type的值,并根据它是 0 还是 1,调用 buildNotificationBigText()buildNotificationBigPicture() 。因此,我编写了 2 种测试方法。在我的测试方法中,我创建了一个RemoteMessage对象并将其传递给onMessageReceived()。但是,这些测试无法正常工作,并且出现以下错误:

java.lang.NullPointerException: Attempt to invoke virtual method 'void in.ac.bits_pilani.goa.ard.services.HandleFirebaseMessages.onMessageReceived(com.google.firebase.messaging.RemoteMessage)' on a null object reference
at in.ac.bits_pilani.goa.ard.activities.MainActivityTest.handleFirebaseMessageBigPicture(MainActivityTest.java:90)
java.lang.NullPointerException: Attempt to invoke virtual method 'void in.ac.bits_pilani.goa.ard.services.HandleFirebaseMessages.onMessageReceived(com.google.firebase.messaging.RemoteMessage)' on a null object reference
    at in.ac.bits_pilani.goa.ard.activities.MainActivityTest.handleFirebaseMessagesBigText(MainActivityTest.java:80)

处理火基消息.java

public class HandleFirebaseMessages extends FirebaseMessagingService {
    /**
     * default id for notification in case specific id is not given in data.
     */
    final int default_id = 42;
    NotificationCompat.Builder builder ;
    /**
     * contains bigTitle value of data in onMessageReceived().
     */
    String bigTitle;
    /**
     * is assigned the bigSummaryText value of data in onMessageReceived().
     */
    String bigSummaryText;
    public HandleFirebaseMessages() {
    }
    /**
     * returns the bitmap image from the url given.
     * @param src image url
     * @return bitmap image at url
     */
    public static Bitmap getBitmapFromURL(final String src) {
        try {
            final URL url = new URL(src);
            final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setDoInput(true);
            connection.connect();
            final InputStream input = connection.getInputStream();
            return BitmapFactory.decodeStream(input);
        } catch (final IOException e) {
            // Log exception
            Log.e("TAG", "fucked man " + e.getMessage());
            return null;
        }
    }
    /**
     * creates the notification when type is 1 or big text.
     * @param data data to be put in notification
     */
    public void buildNotificationBigText(final Map<String, String> data) {
        Log.e("Tag4", "entered buildNotificationBigText");
        //final String bigTitle = data.get("bigTitle");
        final String bigSubTitle = data.get("bigSubTitle");
        //final String bigSummaryText = data.get("bigSummaryText");
        final NotificationCompat.BigTextStyle notificationBigText = new NotificationCompat.BigTextStyle();
        if (bigTitle != null) {
            notificationBigText.setBigContentTitle(bigTitle);
        }
        if (bigSubTitle != null) {
            notificationBigText.bigText(bigSubTitle);
        }
        if (bigSummaryText != null) {
            notificationBigText.setSummaryText(bigSummaryText);
        }
        builder.setStyle(notificationBigText);
    }
    /**
     * creates the notification when type is 2 or big picture.
     * @param data data to be put in notification
     */
    public void buildNotificationBigPicture(final Map<String, String> data) {
        Log.e("Tag3", "entered buildNotificationBigPicture");
        final String imageUrl = data.get("imageUrl");
        //final String bigSummaryText = data.get("bigSummaryText");
        //final String bigTitle = data.get("bigTitle");
        final NotificationCompat.BigPictureStyle notificationBigPicture = new NotificationCompat.BigPictureStyle();
        if (imageUrl != null) {
            final Bitmap image = getBitmapFromURL(imageUrl);
            if (image != null) {
                notificationBigPicture.bigPicture(image);
            } else {
                //TODO Image is null bt url wasn;t!
            }
        }
        if (bigSummaryText != null) {
            notificationBigPicture.setSummaryText(bigSummaryText);
        }
        if (bigTitle != null) {
            notificationBigPicture.setBigContentTitle(bigTitle);
        }
        //TODO icon
        builder.setStyle(notificationBigPicture);
    }
    @Override
    public void onMessageReceived(final RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);
        Log.e("Tag1", "onMessageReceived() started");
        final Map<String, String> data = remoteMessage.getData();
        if (data == null) {
            return;
        }
        bigTitle = data.get("bigTitle");
        bigSummaryText = data.get("bigSummaryText");
        final String type = data.get("type");
        final String id = data.get("id");
        final String smallTitle = data.get("smallTitle");
        final String smallSubTitle = data.get("smallSubTitle");
        //final String contentInfo = data.get("contentInfo");
        //final String ticker = data.get("ticker");
        final String link = data.get("link");
        final String className = data.get("className");
        Log.e("Tag2", "type = " + type);
        builder = new NotificationCompat.Builder(this);
        if (type != null) {
            if (type.compareTo("1") == 0) {
                //Large Text Style corresponds to "1"
                buildNotificationBigText(data);
            } else if (type.compareTo("2") == 0) {
                //BigPicture style specific
                buildNotificationBigPicture(data);
            }
        }
        //General things to be added for any kind of notification
        if (smallTitle != null) {
            builder.setContentTitle(smallTitle);
        }
        if (smallSubTitle != null) {
            builder.setContentText(smallSubTitle);
        }
        int notificationId = default_id;
        if (id != null) {
            notificationId = Integer.parseInt(id);
        }
        builder.setContentIntent(addWebsiteLinkPendingIntent(notificationId, link, className));
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            builder.setCategory(Notification.CATEGORY_SOCIAL);
        }
        builder.setSmallIcon(R.drawable.ic_stat);
        builder.setColor(ContextCompat.getColor(this, R.color.colorPrimary));
        builder.setAutoCancel(true);
        final NotificationManagerCompat mNotificationManager = NotificationManagerCompat.from(this);
        mNotificationManager.notify(notificationId, builder.build());
    }
    /**
     * returns the intent for the webpage or activity to open from the notification.
     * @param id notification id
     * @param link webpage link
     * @param className class for the activity to open
     * @return PendingIntent for the webpage ot activity
     */
    private PendingIntent addWebsiteLinkPendingIntent(final int id, final String link, final String className) {
        Intent intent;
        if (link != null) {
            //TODO Change to ChromeCustomTabs later
            intent = new Intent(Intent.ACTION_VIEW, Uri.parse(link));
        } else if (className != null) {
            try {
                intent = new Intent(this, Class.forName("com.csatimes.dojma." + className));
                //TODO check for page number
            } catch (final ClassNotFoundException e) {
                intent = new Intent(this, MainActivity.class);
            }
            intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
        } else {
            intent = new Intent(this, MainActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION);
        }
        return PendingIntent.getActivity(
                this,
                id,
                intent,
                PendingIntent.FLAG_CANCEL_CURRENT);
    }
}

主要活动测试.java

  @RunWith(AndroidJUnit4.class)
public class MainActivityTest {
    private Context context;
    @Mock
    private HandleFirebaseMessages handleFirebaseMessages;
    @Rule
    public ActivityTestRule<MainActivity> activityTestRule =
            new ActivityTestRule<>(MainActivity.class);
    @Before
    public void init() {
        context = InstrumentationRegistry.getTargetContext();
        //MockitoAnnotations.initMocks(this);
        //handleFirebaseMessages = new HandleFirebaseMessages();
    }
     @Test
        public void handleFirebaseMessagesBigText() {
            HandleFirebaseMessages handleFirebaseMessages=new HandleFirebaseMessages();
            RemoteMessage remoteMessage = new RemoteMessage.Builder("token").addData("type","1").build();
            handleFirebaseMessages.onMessageReceived(remoteMessage);
            Map<String,String> data = new HashMap<>() ;
            data.put("type","1");
            Mockito.verify(handleFirebaseMessages).buildNotificationBigText(data);
        }
        @Test
        public void handleFirebaseMessagesBigPicture() {
            HandleFirebaseMessages handleFirebaseMessages=new HandleFirebaseMessages();
            RemoteMessage remoteMessage = new RemoteMessage.Builder("token").addData("type","2").build();
            handleFirebaseMessages.onMessageReceived(remoteMessage);
            Map<String,String> data = new HashMap<>() ;
            data.put("type","2");
            Mockito.verify(handleFirebaseMessages).buildNotificationBigPicture(data);
        }
}

在测试时,建议限制您正在测试的依赖项。您可以重构代码,使其不依赖于FirebaseMessagingService。

例如,与其将逻辑放在onMessageReceived((中,不如将其提取到其他类中的单独方法(以及HandleFirebaseMessages中的其他方法(,这些类不依赖于FirebaseMessagingService。它甚至可以结构化,使其依赖于纯 java 代码,因此不需要检测来运行测试。

这样,您只会测试代码,而不测试其他依赖项,这将使测试更容易。

相关内容

  • 没有找到相关文章

最新更新