我需要知道如何在 When() mockito 方法中放置方法的接口



我正在尝试在Android Studio中模拟一个带有mockito的方法,但是,演示器类中的一个方法需要一个接口作为参数,但是,当我调用Mockito的When((中的方法时,它无法识别接口。请参阅以下代码:

这是我的 MVP 代码示例。

注册合约界面:

public interface SignUpContract {
interface view{
void showSignInScreen();
void onError(int code, String message);
}
interface model{
interface onFinish<R>{
void onResponse(R data);
void onError(String error);
}
void trySignIn(onFinish onFinish, String name, String password);
}
interface presenter{
void handleSignInButtonClick(String username, String password);
}
}

注册模型:

public class SignUpModel implements SignUpContract.model {
SignUpRepository repository;
public SignUpModel(){}
@Override
public void trySignIn(onFinish onFinish, String name, String password){
repository = new SignUpRepository();
String result = repository.signInUser(name, password);
if(!result.isEmpty()){
onFinish.onResponse(result);
} else {
onFinish.onError("Has error ocurred during the operation");
}
}
}

注册存储库:

public class SignUpRepository {
public String signInUser(String username, String password){
String data = "Someone";
return data;
}
}

注册演示者:

public class SignUpPresenter implements SignUpContract.presenter, 
SignUpContract.model.onFinish {
SignUpContract.view view;
SignUpContract.model model;
public SignUpPresenter(SignUpContract.view view, SignUpContract.model model){
this.view = view;
this.model = model;
}
@Override
public void handleSignInButtonClick(String username, String password) {
try{
model.trySignIn(this, username, password);
}catch (Exception e){
Log.d("",e.getMessage());
}
}
@Override
public void onResponse(Object data) {
view.showSignInScreen();
}
@Override
public void onError(String error) {
view.onError(1, error);
}
}

这是我的测试:

@RunWith(MockitoJUnitRunner.class)
public class SignUpPresenterTest {
public static final String USERNAME = "username";
public static final String PASSWORD = "password";
@Mock SignUpContract.model model;
@Mock SignUpContract.model.onFinish listener;
@Mock SignUpContract.view view;
@InjectMocks SignUpPresenter SUT;
@Before
public void setUp() throws Exception {
SUT = new SignUpPresenter(view, model);
}
public void success() throws Exception {
**when(model.trySignIn(any(SignUpContract.model.onFinish.class), any(String.class), any(String.class))).then(SUT.onResponse(1));**
}
@Test
public void try_signin_success() throws Exception{
success();
ArgumentCaptor<String> ac = ArgumentCaptor.forClass(String.class);
SUT.handleSignInButtonClick(USERNAME, PASSWORD);
verify(model, times(1)).trySignIn(any(SignUpContract.model.onFinish.class), ac.capture(), ac.capture());
List<String> captures = ac.getAllValues();
Assert.assertThat(captures.get(0), is(USERNAME));
Assert.assertThat(captures.get(1), is(PASSWORD));
verify(view).showSignInScreen();
}
}

我将您的代码复制到一个示例中以自己验证这一点。 我做了一些更改,有些只是为了方便我。 请注意,我使用了带有较新的模拟版本(3.2.4(的JUnit5来测试它。

  1. 您不需要同时使用@InjectMocks@Before,其中任何一个就足够了。

  2. 您在doAnswer中使用了错误的参数。应该args[0].

  3. 使用trySignIn(listener, USERNAME, PASSWORD);对我不起作用,因为listener指的是不同的模拟,而您实际上将被测试的类 (SUT( 作为参数传递。

    我将其更改为使用匹配器。


编辑:
我从我的示例中删除了SignUpModelSignUpRespository,因为所有测试所做的只是模拟界面。该实现与您的问题并不真正相关。

listener模拟也不需要,因为它不再使用。

import java.util.List;
import org.junit.Assert;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.stubbing.Answer;
@ExtendWith(MockitoExtension.class)
public class SignUpPresenterTest {
public interface SignUpContract {
interface view {
void showSignInScreen();
void onError(int code, String message);
}
interface model {
interface onFinish<R> {
void onResponse(R data);
void onError(String error);
}
void trySignIn(onFinish onFinish, String name, String password);
}
interface presenter {
void handleSignInButtonClick(String username, String password);
}
}
public static class SignUpPresenter implements SignUpContract.presenter, SignUpContract.model.onFinish {
SignUpContract.view view;
SignUpContract.model model;
public SignUpPresenter(SignUpContract.view view, SignUpContract.model model) {
this.view = view;
this.model = model;
}
@Override
public void handleSignInButtonClick(String username, String password) {
try {
model.trySignIn(this, username, password);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onResponse(Object data) {
view.showSignInScreen();
}
@Override
public void onError(String error) {
view.onError(1, error);
}
}
private static final String USERNAME = "username";
private static final String PASSWORD = "password";
@Mock
SignUpContract.model model;
@Mock
SignUpContract.view view;
SignUpPresenter SUT;
@BeforeEach
public void setUp() throws Exception {
SUT = new SignUpPresenter(view, model);
}
@Test
public void try_signin_success() throws Exception {
Mockito.doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
SignUpContract.model.onFinish callback = (SignUpContract.model.onFinish) args[0];
callback.onResponse(0);
return null;
}
}).when(model).trySignIn(Mockito.any(SignUpContract.model.onFinish.class), Mockito.eq(USERNAME), Mockito.eq(PASSWORD));
ArgumentCaptor<String> ac = ArgumentCaptor.forClass(String.class);
SUT.handleSignInButtonClick(USERNAME, PASSWORD);
Mockito.verify(model, Mockito.times(1)).trySignIn(Mockito.any(SignUpContract.model.onFinish.class), ac.capture(), ac.capture());
List<String> captures = ac.getAllValues();
Assert.assertEquals(USERNAME, captures.get(0));
Assert.assertEquals(PASSWORD, captures.get(1));
Mockito.verify(view).showSignInScreen();
}
}

请注意,验证trySignIn调用并不是真正必要的,因为如果不调用模拟上的行为定义,您的测试将不起作用。因此,这已经通过测试流程进行了验证。

还要尝试遵循 Java 命名约定:类名/接口名应以大写字母开头。这通常使代码更易于阅读。

最新更新