firebase / firebase-admin-java

Firebase Admin Java SDK
https://firebase.google.com/docs/admin/setup
Apache License 2.0
525 stars 255 forks source link

[FR] - Need a setter to set FCM host for Functional tests/Service Level tests. #802

Open yashjain12yj opened 1 year ago

yashjain12yj commented 1 year ago

Summary: I recently integrated FCM SDK to send Push Notifications. The integration was very simple and smooth but while I started writing Functional Tests, I got to know that I can't give FCM host while constructing a FcmMessaging object. The FCM_URL is hardcoded in the FirebaseMessagingClientImpl class, which is restricting me from writing functional tests.

Solution: While constructing the FcmMessaging object or while initializing FirebaseApp there can be an option to pass the FCM host. If the host is not passed then the default hardcoded host must be used.

Describe alternatives you've considered Currently, due to this, I'm blocked from writing FTs. I'm currently only dependent on UTs

google-oss-bot commented 1 year ago

I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.

yashjain12yj commented 1 year ago

I have created this PR for the above-mentioned request. @lahirumaramba Could you please check once?

bashbers commented 8 months ago

Hey @yashjain12yj, might be too late for you since it's currently november but I implemented a work-around for this issue using reflection.

/**
   * Override the internal fcm.googleapis.com URL with a gateway URL. This function is needed due to
   * the FirebaseClient interface missing a property to configure the FCM url.
   *
   * @throws Exception ReflectionBased errors, could be encountered once the {@link FirebaseClient}
   *     interface is changed.
   */
  private void overrideFcmUrl() throws Exception { 
    var instance = FirebaseMessaging.getInstance();
    var clientSupplierField = instance.getClass().getDeclaredField("messagingClient");
    clientSupplierField.setAccessible(true);
    var clientSupplier = (Supplier<?>) clientSupplierField.get(instance);
    var messager = clientSupplier.get();
    var urlField = messager.getClass().getDeclaredField("fcmSendUrl"); 
    setFinal(messager, urlField, gatewaySendUrl); 
  }

  /**
   * Helper function to override private final fields in Objects.
   *
   * @param instance Object that contains {@link Field}
   * @param field Field that should be changed
   * @param newValue any value
   * @throws Exception ReflectionBased errors, could be encountered once the {@link FirebaseClient}
   *     interface is changed
   */
  private void setFinal(Object instance, Field field, Object newValue) throws Exception { 
    field.setAccessible(true);
    Field modifiersField = Field.class.getDeclaredField("modifiers"); 
    modifiersField.setAccessible(true); 
    modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); 
    field.set(instance, newValue);
  }

This effectively rewrites the fcmSendUrl which can then be used for testing. Hope this is of any help!

ajax-semenov-y commented 5 months ago

+1, we are also experiencing the issue described in this ticket

martinboue commented 2 weeks ago

Any update on this issue? The PR is waiting for review. Thanks!