【问题标题】:Mockito and callback returning "Argument(s) are different!"Mockito 和回调返回“Argument(s) are different!”
【发布时间】:2023-03-15 21:13:01
【问题描述】:

我正在尝试在 android 上使用 mockito。我想将它与一些回调一起使用。 这是我的测试:

public class LoginPresenterTest {


private User mUser = new User();

@Mock
private UsersRepository mUsersRepository;

@Mock
private LoginContract.View mLoginView;

/**
 * {@link ArgumentCaptor} is a powerful Mockito API to capture argument values and use them to
 * perform further actions or assertions on them.
 */
@Captor
private ArgumentCaptor<LoginUserCallback> mLoadLoginUserCallbackCaptor;

private LoginPresenter mLoginPresenter;

@Before
public void setupNotesPresenter() {
    // Mockito has a very convenient way to inject mocks by using the @Mock annotation. To
    // inject the mocks in the test the initMocks method needs to be called.
    MockitoAnnotations.initMocks(this);

    // Get a reference to the class under test
    mLoginPresenter = new LoginPresenter(mUsersRepository, mLoginView);

    // fixtures
    mUser.setFirstName("Von");
    mUser.setLastName("Miller");
    mUser.setUsername("von.miller@broncos.us");
    mUser.setPassword("Broncos50superBowlWinners");
}

@Test
public void onLoginFail_ShowFail() {

    // When try to login
    mLoginPresenter.login("von.miller@broncos.us", "notGoodPassword");


    // Callback is captured and invoked with stubbed user
    verify(mUsersRepository).login(eq(new User()), mLoadLoginUserCallbackCaptor.capture());
    mLoadLoginUserCallbackCaptor.getValue().onLoginComplete(eq(mUser));

    // The login progress is show
    verify(mLoginView).showLoginFailed(anyString());
}

但我收到了这个错误:

Argument(s) are different! Wanted:
mUsersRepository.login(
    ch.example.project.Model.User@a45f686,
    <Capturing argument>
);
-> at example.ch.project.Login.LoginPresenterTest.onLoginFail_ShowFail(LoginPresenterTest.java:94)
Actual invocation has different arguments:
mUsersRepository.login(
    ch.example.project.Model.User@773bdcae,
    ch.example.project.Login.LoginPresenter$1@1844b009
);

也许问题在于第二个实际参数是 ch.example.project.Login.LoginPresenter$1@1844b009 ?

我关注了:https://codelabs.developers.google.com/codelabs/android-testing/#5

感谢您的帮助 =)

编辑

我尝试测试的方法(LoginPresenter):

@Override
public void login(String email, String password) {

    mLoginView.showLoginInProgress();

    User user = new User();
    user.setUsername(email);
    user.setPassword(password);

    mUsersRepository.login(user, new UsersRepository.LoginUserCallback() {

        @Override
        public void onLoginComplete(User loggedUser) {
            mLoginView.showLoginComplete();
        }

        @Override
        public void onErrorAtAttempt(String message) {
            mLoginView.showLoginFailed(message);
        }
    });

}

【问题讨论】:

    标签: android junit mockito junit4


    【解决方案1】:
    eq(new User())
    

    当使用eq(或根本不使用匹配器)时,Mockito 使用传入实例的equals 方法比较参数。除非您为用户对象定义了灵活的equals 实现,否则这是很可能会失败。

    考虑使用isA(User.class),这将简单地验证对象instanceof User、或any()anyObject()完全跳过匹配第一个参数。

    【讨论】:

    • 谢谢你的回答,但是当我在我的用户之前删除 eq() 时,我得到了一个新的错误:“org.mockito.exceptions.misusing.InvalidUseOfMatchersException: Invalid use of argument matchers!2 matchers预期,1 记录:-> at .Login.LoginPresenterTest.onLoginFail_ShowFail(LoginPresenterTest.java:94) 如果匹配器与原始值组合,则可能发生此异常: //incorrect: someMethod(anyObject(), "raw String"); When使用匹配器时,所有参数都必须由匹配器提供。例如: //correct: someMethod(anyObject(), eq("String by matcher"));
    • @Xero:使用 Matchers 时,每个参数需要使用一个 Matcher(或 Captor),用于implementation-specific reasons。这就是为什么我不建议只删除eq,而是将表达式替换为我列出的三个匹配器之一(isAanyanyObject)。
    • 我在用户上尝试了 isA、any 和 anyObject,但我得到了同样的错误。你不认为错误来自第二个参数?
    • 我用我正在尝试测试的方法编辑了我的帖子,它可能会有所帮助
    • 我让您的代码在我的机器上运行,重现了问题并应用了 Jeff 修复 - 一切正常。您的代码中还有另一个错误,但休息很好。你确定这条线:verify(mUsersRepository).login(isA(User.class), mLoadLoginUserCallbackCaptor.capture()); 仍然失败吗?此外,您可能希望将上次验证​​更改为:mLoadLoginUserCallbackCaptor.getValue().onErrorAtAttempt("error");
    【解决方案2】:

    我在 rxjava 2 和 dagger 2 中使用 mvp 模式,并且一直坚持使用 Mockito 对演示者进行单元测试。给我“参数不同!”的代码错误:

    @Mock
    ImageService imageService;
    
    @Mock
    MetadataResponse metadataResponse;
    
    private String imageId = "123456789";
    
    @Test
    public void getImageMetadata() {
        when(imageService.getImageMetadata(imageId)).thenReturn(Observable.just(Response.success(metadataResponse)));
    
        presenter.getImageMetaData(imageId);
        verify(view).showImageData(new ImageData()));
    }
    

    这会引发如下错误消息:

    参数不同!通缉:实际调用有不同 参数:com.example.model.ImageData@5q3v861

    感谢@Jeff Bowman 的回答,在我更改此行后它起作用了

    verify(view).showImageData(new ImageData()));
    

    verify(view).showImageData(isA(ImageData.class));
    

    【讨论】:

      猜你喜欢
      • 2022-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-13
      • 1970-01-01
      • 1970-01-01
      • 2011-09-06
      • 1970-01-01
      相关资源
      最近更新 更多