如何验证方法在模拟类的回调中运行? [英] How can I verify a method is run in a mocked class's callback?

查看:105
本文介绍了如何验证方法在模拟类的回调中运行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的Android代码中有一个实用程序类,用于处理用户身份验证.我正在用Mokcito编写此类的单元测试,以验证是否已成功创建或创建新用户而通知了侦听器.这是该实用工具类的方法之一:

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();
            });
}

我正在模拟FirebaseAuth,并且我想验证是否已调用authListener.newUserCreated().我曾尝试使用深层存根和参数捕获器来处理firebaseAuth.createUserWithEmailAndPassword上的链接方法调用,但我不知道如何使它起作用.

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.

更新

这是我的测试类,其中包含此方法的测试:

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();
    }

}

会引发异常

java.lang.ExceptionInInitializerError在 com.google.android.gms.tasks.zzn.addOnSuccessListener(未知来源) ...原因:java.lang.RuntimeException:方法getMainLooper in android.os.Looper没有被嘲笑.

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.

推荐答案

使用Mockito.when来使createUserCall返回模拟的Task. 然后Mockito.verify完成任务,以捕获添加侦听器调用的参数.

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).

此方法实际上不会测试是否调用了侦听器.只是调用了add listener方法,并且回调在调用时做了应做的事情

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();

这篇关于如何验证方法在模拟类的回调中运行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆