firebase / firebase-admin-dotnet

Firebase Admin .NET SDK
https://firebase.google.com/docs/admin/setup
Apache License 2.0
370 stars 131 forks source link

How to use IHttpClientFactory with Firebase Admin #253

Closed kaylumah closed 4 years ago

kaylumah commented 4 years ago

Microsoft has a number of Extension packages like https://docs.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests

Using the IHttpClientFactory you get the best practices for using HttpClients. This way it is easy to get extra logging, interception pipeline and testing for the underlying HTTP Calls. Is it possible to use this with the Firebase SDK?

hiranya911 commented 4 years ago

This library is based on Google API client for .NET, which provides its own HttpClientFactory API: https://googleapis.dev/dotnet/Google.Apis.Core/latest/api/Google.Apis.Http.HttpClientFactory.html

You can implement your own, and pass an instance via AppOptions. We use it for our own unit testing: https://github.com/firebase/firebase-admin-dotnet/blob/ad97c69c21d23dfd1ea4993e1da9681b27a6f04e/FirebaseAdmin/FirebaseAdmin.Tests/Messaging/FirebaseMessagingClientTest.cs#L85-L93

You can also use it for logging, proxy configuration and a range of other use cases.

kaylumah commented 4 years ago

@hiranya911 As described in the linked issue I found away around this :-) Still have a couple of questions if you do not mind. In my scenario I have a service, lets call it PushNotificationService that depends on this library. This service creates the FirebaseApp and FirebaseMessagingClient; it checks with FirebaseApp.GetInstance() if it is already created.

  1. In the linked test cases you use SingleMessageResponse which is internal, so to return it I have to duplicate it on my end. Is there a beter approach to this?
  2. How do I mock the service account credentials. I can call FirebaseApp.Create in my test code, so my service code won't try to create it again (there is an instance with the same name then), but in the referenced sample a service-account.json is used which looks like real credentials. So how would I go around that
hiranya911 commented 4 years ago

In the linked test cases you use SingleMessageResponse which is internal, so to return it I have to duplicate it on my end. Is there a beter approach to this?

I would generally recommend a more blackbox approach for testing. Instead of mocking the possible network interactions of the SDK, just put the whole thing behind an interface.

interface NotificationSender {
  Task<string> SendNotification(string title, string body);
}

Now you can have one implementation that uses the SDK, and a test implementation that doesn't make any HTTP calls. This makes your test code less dependent on how the SDK chooses to implement a certain API under the hood.

How do I mock the service account credentials.

You can use some form of mock GoogleCredentials. See https://github.com/firebase/firebase-admin-dotnet/blob/ad97c69c21d23dfd1ea4993e1da9681b27a6f04e/FirebaseAdmin/FirebaseAdmin.Tests/Messaging/FirebaseMessagingClientTest.cs#L32-L33