Mockito可以模拟相同方法调用,但使用不同的集合参数。

huangapple go评论66阅读模式
英文:

Mockito mock same method calls with different collection-arguments

问题

我尝试模拟相同方法调用,但使用不同的集合参数。

我的问题是,我没有从输入的模拟调用中获得正确的模拟答案。

测试类:

@ExtendWith(SpringExtension.class)
public class CollectionTest {

	@MockBean
	private Controller c;
	
	@BeforeEach
	public void init() {
		Collection<String> a = Mockito.anyCollection();
		a.add("a");
		Mockito.when(c.run(a)).thenReturn("a");
		
		Collection<String> b = Mockito.anyCollection();
		b.add("b");
		Mockito.when(c.run(b)).thenReturn("b");
	}

	@Test
	public void test() {
		assertEquals("a", c.run(Lists.newArrayList("a"))); // 不起作用!!! 返回 "b" 但应返回 "a"
		assertEquals("b", c.run(Lists.newArrayList("b"))); // 
	}
}

控制器类:

@Service
public class Controller{
	public String run(Collection<String> c) {
		return "not-mocked";
	}	
}

我不知道为什么它不返回 "a"。我尝试将集合更改为字符串,但行为相同。

要获得以下行为,需要执行以下步骤:

@Test
public void test() {
	assertEquals("a", c.run(Lists.newArrayList("a"))); // 应返回 "a"
	assertEquals("b", c.run(Lists.newArrayList("b"))); // 应返回 "b"
}

我使用的是 Java Mockito "3.1" 和 Spring,但我认为 Mockito 是关键信息。

英文:

I try to mock same method calls with different collection-arguments.

My problem is that im not getting the correct mocked-answer from Mocked-Call for the input.

Test-Class:

@ExtendWith(SpringExtension.class)
public class CollectionTest {

	@MockBean
	private Controller c;
	
	@BeforeEach
	public void init() {
		Collection&lt;String&gt; a = Mockito.anyCollection();
		a.add(&quot;a&quot;);
		Mockito.when(c.run(a)).thenReturn(&quot;a&quot;);
		
		Collection&lt;String&gt; b = Mockito.anyCollection();
		b.add(&quot;b&quot;);
		Mockito.when(c.run(b)).thenReturn(&quot;b&quot;);
	}

	@Test
	public void test() {
		assertEquals(&quot;a&quot;, c.run(Lists.newArrayList(&quot;a&quot;))); // DOESNT&#39;WORK!!! Returns &quot;b&quot; but should &quot;a&quot;
		assertEquals(&quot;b&quot;, c.run(Lists.newArrayList(&quot;b&quot;))); // 
	}
}

Controller-Class:

@Service
public class Controller{
	public String run(Collection&lt;String&gt; c) {
		return &quot;not-mocked&quot;;
	}	
}

I'v got no idea why it doesn't return "a". I tried to change the collection to string but same behaviour.

What are the Steps to do, to get the following behaviour?

@Test
public void test() {
	assertEquals(&quot;a&quot;, c.run(Lists.newArrayList(&quot;a&quot;))); // should return &quot;a&quot;
	assertEquals(&quot;b&quot;, c.run(Lists.newArrayList(&quot;b&quot;))); // should return &quot;b&quot;
}

Im using Java Mockito "3.1" and Spring, but I think Mockito is the important information here.

答案1

得分: 3

你的第二个调用 - Mockito.when(c.run(b)).thenReturn("b"); 覆盖了我们的第一个调用,因此Mockito将始终返回 "b"。
如果你需要从同一个调用中获取多个答案,你可以使用变长参数的变体:

when(c.run(anyCollection())).thenReturn("a", "b");

现在控制器的run方法的第一个调用将返回 "a",所有后续调用都将返回 "b"。你可以提供任意多个返回结果,最后一个将从那时开始重复作为答案。

英文:

Your second call - Mockito.when(c.run(b)).thenReturn("b");
is overruling our first call so Mockito will therefore always return "b".
If you need multiple answers from the same call, you can use the varags variant:

when(c.run(anyCollection())).thenReturn("a", "b");

Now the first call to the controller's run method will return "a" and all subsequent calls will return "b". You can provide as many return results as you want and the last one will be repeated from then on as the answer.

答案2

得分: 1

以下是翻译好的部分:

写两个测试用例,将展示您期望的结果。
您向同一个控制器添加了两个不同的结果,因此您只会得到最后一个:Mockito.when(c.run(b)).thenReturn("b");
正常情况下,setUp() 中的最后一个模拟的期望结果将保留在内存中。

之前的答案是:
您可以使用像JUnit和Mockito这样的工具来测试您的Spring Web MVC应用程序。
它看起来像这样:

@WebMvcTest(controllers = UserController.class)
@ActiveProfiles("test")
class UserControllerTest {
   
    @Autowired                           
    private MockMvc mockMvc;  
    
    @MockBean                           
    private UserService userService; 
    
    private List<User> userList;       
    
    @BeforeEach                           
    void setUp() {                               
       this.userList = new ArrayList<>();
       this.userList.add(new User(1L, "user1@gmail.com", "pwd1","User1"));
       this.userList.add(new User(2L, "user2@gmail.com", "pwd2","User2"));
       this.userList.add(new User(3L, "user3@gmail.com", "pwd3","User3"));                                                       
    }
}

作为示例:

@Test
void shouldFetchAllUsers() throws Exception {
    given(userService.findAllUsers()).willReturn(userList);
    this.mockMvc.perform(get("/api/users"))
        .andExpect(status().isOk())
        .andExpect(jsonPath("$.size()", is(userList.size())));
}

示例来自于 @see https://medium.com/backend-habit/integrate-junit-and-mockito-unit-testing-for-controller-layer-91bb4099c2a5

英文:

Write two tests will show you the results you are expecting.
You are adding to the same Controller two different results so you get only the last one : Mockito.when(c.run(b)).thenReturn(&quot;b&quot;);
Normal. The last mocked expected result in your setUp() will stay in memory.

Previous answer was :
You can use something like junit and mockito to test your spring-web-mvc application.
It looks like that :

@WebMvcTest(controllers = UserController.class)
@ActiveProfiles(&quot;test&quot;)
class UserControllerTest {
   
    @Autowired                           
    private MockMvc mockMvc;  
                                                 
    @MockBean                           
    private UserService userService; 
                                               
    private List&lt;User&gt; userList;       
                                            
    @BeforeEach                           
    void setUp() {                               
       this.userList = new ArrayList&lt;&gt;();
       this.userList.add(new User(1L, &quot;user1@gmail.com&quot;, &quot;pwd1&quot;,&quot;User1&quot;));
       this.userList.add(new User(2L, &quot;user2@gmail.com&quot;, &quot;pwd2&quot;,&quot;User2&quot;));
       this.userList.add(new User(3L, &quot;user3@gmail.com&quot;, &quot;pwd3&quot;,&quot;User3&quot;));                                                       
    }
}

And as an example :

@Test
void shouldFetchAllUsers() throws Exception {
	given(userService.findAllUsers()).willReturn(userList);
	this.mockMvc.perform(get(&quot;/api/users&quot;))
		.andExpect(status().isOk())
		.andExpect(jsonPath(&quot;$.size()&quot;, is(userList.size() )));
}

Example from @see https://medium.com/backend-habit/integrate-junit-and-mockito-unit-testing-for-controller-layer-91bb4099c2a5

huangapple
  • 本文由 发表于 2020年8月8日 03:13:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/63307907.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定