71363

How can I verify a method is run in a mocked class's callback?

Question:

I have a utility class in my Android code that handles the authentication of users. I'm writing unit tests for this class with Mokcito to verify that a listener is being notified if the creation of a new user had succeeded or failed. Here is one of this utility class's methods:

public void createNewUser(String email, String password) { firebaseAuth.createUserWithEmailAndPassword(email, password) .addOnSuccessListener(authResult -> { authListener.newUserCreated(); }) .addOnFailureListener(e -> { authListener.failedCreatingNewUser(); }); }

I am mocking FirebaseAuth and I want to verify that authListener.newUserCreated() has been called. I have tried using deep stubs and argument captors to handle the chained method calls on firebaseAuth.createUserWithEmailAndPassword but I can't figure out how to get this working.

<strong>UPDATE</strong>

Here is my test class with the test for this method:

public class AuthUtilsTest { private static final String USERNAME = "USERNAME"; private static final String PASSWORD = "PASSWORD"; @Mock private FirebaseAuth firebaseAuth; @Mock private FirebaseFirestore firebaseFirestore; @Mock private BaseEncoding base64; @Mock private PreferencesRepo preferencesRepo; @Mock private AuthUtilsContract.EventListener eventListener; private AuthUtils authUtils; @Before public void setupAuthUtils() { MockitoAnnotations.initMocks(this); authUtils = new AuthUtils( preferencesRepo, firebaseAuth, firebaseFirestore, base64 ); authUtils.takeEventListener(eventListener); } @Test public void failureCreatingNewUserTellsListener() { Task<AuthResult> failedTask = Tasks.forException(new Exception("fail")); when(firebaseAuth.createUserWithEmailAndPassword(anyString(), anyString())).thenReturn(failedTask); authUtils.createNewUser(USERNAME, PASSWORD); verify(eventListener).failedCreatingNewUser(); } }

which throws the exception

<blockquote>

java.lang.ExceptionInInitializerError at com.google.android.gms.tasks.zzn.addOnSuccessListener(Unknown Source) ... Caused by: java.lang.RuntimeException: Method getMainLooper in android.os.Looper not mocked.

</blockquote>

Answer1:

Use Mockito.when to make the createUserCall return a mocked Task. Then Mockito.verify on the task to capture the arguments to the add listener call.

Test the captured arguments to the extent you heart desires (this is like a unit test within a unit test, the captured arguments are your new Classes under test).

This method won't actually test that the listeners are called. Just that the add listener method was called and that the callbacks do what they should when called

verify(mockTask).addOnSuccessListener(listenerCaptor.capture()); OnSuccessListener<Auth> newObjectUnderTest = listenerCaptor.getValue(); //ACT newObjectUnderTest.onSuccess(auth); //ASSERT verify(authListener).newUserCreated();

Answer2:

Use Mockito.when to make the createUserCall return an already completed Task<AuthResult>.

Then Mockito.verify that the authListener did what it should assuming authListener is also a mock

Recommend

  • How to wait for a function to complete before executing another function
  • Automatically fetching latest version of a file on import
  • Android Firebase cannot refresh email verification status
  • Android auth firebase error: Local module descriptor class for com.google.firebase.auth not found
  • Visual Studio need to rebuild solution for every change
  • I try to sort an array using sort() but it fails
  • wordpress wpdb->update not working
  • getCurrentUser() functions error
  • How to return an object in my case?
  • Firebase Google Sign-In will not work (Android)
  • copy an attribute of a property from one instance to another instance (of a different type ) at runt
  • Cannot use a lambda expression as an argument to a dynamically dispatched operation
  • cell spacing in div table
  • XSLT foreach repeating nodes to flat
  • How to create a 2D image by rotating 1D vector of numbers around its center element?
  • Thread 1: EXC_BAD_ACCESS (code =1 address = 0x0)
  • Unity3D & Android: Difference between “UnityMain” and “main” threads?
  • Django rest serializer Breaks when data exists
  • How to rebase a series of branches?
  • Display issues when we change from one jquery mobile page to another in firefox
  • Deselecting radio buttons while keeping the View Model in synch
  • Azure Cloud Service Web Role web pages do not load
  • Does CUDA 5 support STL or THRUST inside the device code?
  • JSON with duplicate key names losing information when parsed
  • Trying to switch camera back to front but getting exception
  • what is the difference between the asp.net mvc application and asp.net web application
  • Jquery - Jquery Wysiwyg return html as a string
  • Why winpcap requires both .lib and .dll to run?
  • Matrix multiplication with MKL
  • PHP: When would you need the self:: keyword?
  • Free memory of cv::Mat loaded using FileStorage API
  • How to set the response of a form post action to a iframe source?
  • Hits per day in Google Big Query
  • Angular 2 constructor injection vs direct access
  • File not found error Google Drive API
  • How to get Windows thread pool to call class member function?
  • Are Kotlin's Float, Int etc optimised to built-in types in the JVM? [duplicate]
  • unknown Exception android
  • Programmatically clearing map cache
  • Converting MP3 duration time