在Mockito中多次使用相同的ArgumentMatchers

时间:2021-07-29 20:01:42

I've been learning about tests lately but this is the first test were I've had to pass a variable in a function that I'm mocking. I've written a similar test were the only difference is that i use an ArgumentMatcher in this test because the testInput.validate() needs 3 Strings to pass with it. I don't know this stuff very well so I'm sorry if the terminology is off.

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

Here is the code i'm trying to test:

这是我要测试的代码:

@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");
    }
  }
}

And here is my test:

这是我的测试:

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

I had a bunch of errors with this code and when I changed the ArgumentMatchers.anyString() to just ArgumentMatchers.any() I had 1 error instead of like 5.

我有这个代码的一堆错误,当我将ArgumentMatchers.anyString()更改为ArgumentMatchers.any()时,我有1个错误而不是5个错误。

2 个解决方案

#1


1  

I looked into the source code of this problem, and for information to other readers, the underlying problem was that the mocked function was declared "static". This is not evident from the posted problem.

我查看了这个问题的源代码,并且对于其他读者的信息,潜在的问题是模拟的函数被声明为“静态”。发布的问题并不明显。

#2


1  

There are many issues in your test.

您的测试中存在许多问题。

  1. You cannot use like this

    你不能这样使用

    String test = ArgumentMatchers.anyString();
    Mockito.when(testInput.validate(test, test, test)).thenReturn(true, false); 
    

    You can clearly see from the error message what Mockito is saying when you do this

    您可以从错误消息中清楚地看到Mockito在您执行此操作时所说的内容

    org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
    Invalid use of argument matchers!
    3 matchers expected, 1 recorded:
    

    which means you need to pass three different instances.

    这意味着你需要传递三个不同的实例。

  2. This line is also not correct

    这条线也不正确

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

findById should return Optional, but you are returning boolean. When you use Mockito, you should mock individual steps. What I mean is in your example you need to mock userRepository.findById(test) and then isPresent on that returned mock. You cannot skip one step and go to the next.

findById应该返回Optional,但是你返回boolean。当你使用Mockito时,你应该模拟各个步骤。我的意思是在你的例子中,你需要模拟userRepository.findById(test),然后在返回的mock上使用isPresent。你不能跳过一步,然后转到下一步。

Here is a working code

这是一个有效的代码

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

#1


1  

I looked into the source code of this problem, and for information to other readers, the underlying problem was that the mocked function was declared "static". This is not evident from the posted problem.

我查看了这个问题的源代码,并且对于其他读者的信息,潜在的问题是模拟的函数被声明为“静态”。发布的问题并不明显。

#2


1  

There are many issues in your test.

您的测试中存在许多问题。

  1. You cannot use like this

    你不能这样使用

    String test = ArgumentMatchers.anyString();
    Mockito.when(testInput.validate(test, test, test)).thenReturn(true, false); 
    

    You can clearly see from the error message what Mockito is saying when you do this

    您可以从错误消息中清楚地看到Mockito在您执行此操作时所说的内容

    org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
    Invalid use of argument matchers!
    3 matchers expected, 1 recorded:
    

    which means you need to pass three different instances.

    这意味着你需要传递三个不同的实例。

  2. This line is also not correct

    这条线也不正确

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

findById should return Optional, but you are returning boolean. When you use Mockito, you should mock individual steps. What I mean is in your example you need to mock userRepository.findById(test) and then isPresent on that returned mock. You cannot skip one step and go to the next.

findById应该返回Optional,但是你返回boolean。当你使用Mockito时,你应该模拟各个步骤。我的意思是在你的例子中,你需要模拟userRepository.findById(test),然后在返回的mock上使用isPresent。你不能跳过一步,然后转到下一步。

Here is a working code

这是一个有效的代码

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