Java 多次在Mockito.when中使用相同的参数匹配器

Java 多次在Mockito.when中使用相同的参数匹配器,java,junit,mocking,mockito,Java,Junit,Mocking,Mockito,我最近一直在学习测试,但这是第一个测试,因为我必须在模拟的函数中传递一个变量。我编写了一个类似的测试,唯一的区别是我在这个测试中使用了ArgumentMatcher,因为testInput.validate()需要3个字符串才能传递。我对这些东西不太了解,所以如果术语不通,我很抱歉 下面是我要测试的代码: @Component public class RequestHandler { private static Gson gson = new Gson(); private final U

我最近一直在学习测试,但这是第一个测试,因为我必须在模拟的函数中传递一个变量。我编写了一个类似的测试,唯一的区别是我在这个测试中使用了ArgumentMatcher,因为testInput.validate()需要3个字符串才能传递。我对这些东西不太了解,所以如果术语不通,我很抱歉

下面是我要测试的代码:

@Component
public class RequestHandler {

private static Gson gson = new Gson();
private final UserRepository userRepository;
private final TestInput testInput;

@Autowired
public RequestHandler(UserRepository userRepository, TestInput testInput) {
    this.userRepository = UserRepository;
    this.testInput = testInput;
}

public String addUser(String username, String email, String password) {
    if (testInput.validate(username, email, password) && !(userRepository.findById(email).isPresent())) {
        User user = new User(username, email, password);
        userRepository.save(user);
        return gson.toJson(user);
    } else {
        return gson.toJson("error");
    }
  }
}
这是我的测试:

public class RequestHandlerTest {
    UserRepository userRepository = Mockito.mock(UserRepository.class);
    TestInput testInput = Mockito.mock(TestInput.class);

    RequestHandler requestHandler = new RequestHandler(userRepository, testInput);

    String test = ArgumentMatchers.anyString();

    @Test
    public void addUserTest() {
        Mockito.when(testInput.validate(test, test, test)).thenReturn(true, false); 

        Mockito.when(userRepository.findById(test).isPresent()).thenReturn(false, true);

        String jsonUser = new Gson().toJson(new User("username123","example@mail.com","12344321"));
        String jsonError = new Gson().toJson("error");

        System.out.println("addUser Test1");
        assertEquals(jsonUser, requestHandler.addUser("username123","example@mail.com","12344321"));

        System.out.println("addUser Test2");
        assertEquals(jsonError, requestHandler.addUser("username123","example@mail.com","12344321"));
    }
}

我在这段代码中遇到了一系列错误,当我将ArgumentMatchers.anyString()更改为ArgumentMatchers.any()时,我出现了1个错误,而不是5个错误。

测试中存在许多问题

  • 你不能这样使用

    String test = ArgumentMatchers.anyString();
    Mockito.when(testInput.validate(test, test, test)).thenReturn(true, false); 
    
    当您这样做时,您可以从错误消息中清楚地看到Mockito在说什么

    org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
    Invalid use of argument matchers!
    3 matchers expected, 1 recorded:
    
    这意味着您需要传递三个不同的实例

  • 这一行也不正确

    Mockito.when(userRepository.findById(test).isPresent()).thenReturn(false, true);
    
  • findById
    应返回可选值,但返回的是布尔值。当您使用Mockito时,您应该模拟各个步骤。我的意思是,在您的示例中,您需要模拟
    userRepository.findById(test)
    ,然后在返回的模拟上显示
    isPresent
    。你不能跳过一步而转到下一步

    这是一个工作代码

    public class RequestHandlerTest {
        UserRepository userRepository = Mockito.mock(UserRepository.class);
        TestInput testInput = Mockito.mock(TestInput.class);
    
        RequestHandler requestHandler = new RequestHandler(userRepository, testInput);
    
        @Test
        public void addUserTest() {
            when(testInput.validate(anyString(), anyString(), anyString())).thenReturn(true, false);
    
    
            User username123 = new User("username123", "example@mail.com", "12344321");
            String jsonUser = new Gson().toJson(username123);
            String jsonError = new Gson().toJson("error");
    
    
            when(userRepository.findById(anyString())).thenReturn(Optional.empty(),Optional.of(username123));
            System.out.println("addUser Test1");
            assertEquals(jsonUser, requestHandler.addUser("username123","example@mail.com","12344321"));
    
            System.out.println("addUser Test2");
            assertEquals(jsonError, requestHandler.addUser("username123","example@mail.com","12344321"));
        }
    }
    

    我研究了这个问题的源代码,为了向其他读者提供信息,潜在的问题是模拟函数被声明为“静态”。从发布的问题来看,这一点并不明显。

    您的问题是正确的,但“您需要传递三个不同的实例”还不够:实例必须在调用
    时内联到
    ,因为调用才是重要的,而不是匹配器的返回值(即
    null
    )。