美文网首页
Mockito的参数匹配器

Mockito的参数匹配器

作者: 一路花开_8fab | 来源:发表于2019-04-14 21:50 被阅读0次

    该系列文章翻译自https://www.baeldung.com/mockito-series

    1.maven依赖

    <dependency>
        <groupId>org.mockito</groupId> 
        <artifactId>mockito-core</artifactId>
        <version>2.21.0</version> 
        <scope>test</scope>
    </dependency>
    

    Mockito的最新版本请参考https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22org.mockito%22%20AND%20a%3A%22mockito-core%22

    2.参数匹配器

    下面的例子中,当analyze方法接受的参数是"poppy"时,会返回"Flower"

    doReturn("Flower").when(flowerService).analyze("poppy");
    

    如果要做到,不管接受的参数是什么,都会返回"Flower",则需要用到anyString匹配器

    when(flowerService.analyze(anyString())).thenReturn("Flower");
    

    注意,当使用参数匹配器时,必须所有的参数都要用匹配器的方式,而不允许一部分参数是固定值,一部分参数试用匹配器,下面是一个错误的示例:

    abstract class FlowerService {
        public abstract boolean isABigFlower(String name, int petals);
    }
     
    FlowerService mock = mock(FlowerService.class);
     
    when(mock.isABigFlower("poppy", anyInt())).thenReturn(true);
    

    可使用eq匹配器修改如下:

    when(mock.isABigFlower(eq("poppy"), anyInt())).thenReturn(true);
    

    在使用匹配器时,有两点注意事项

    1. 不能将匹配器作为返回值,而需要返回精确的值
    2. 只能在校验或者模拟过程中使用匹配器,否则Mockito会抛出InvalidUseOfMatchersException异常。

    针对第二个情况,一个错误的示例如下:

    String orMatcher = or(eq("poppy"), endsWith("y"));
    verify(mock).analyze(orMatcher);
    

    可修改为:

    verify(mock).analyze(or(eq("poppy"), endsWith("y")));
    

    在上面的例子中可以看到,Mockito支持在参数匹配器上进行常规的逻辑运算,如‘not’、 ‘and’、‘or’.

    3. 自定义参数匹配器

    
    @Controller
    @RequestMapping("/message")
    public class MessageController {
    
        @Autowired
        private MessageService messageService;
    
        @PostMapping
        public Message createMessage (@RequestBody MessageApi messageDTO) {
            Message message = new Message();
            message.setText(messageDTO.getText());
            message.setFrom(messageDTO.getFrom());
            message.setTo(messageDTO.getTo());
            message.setDate(Date.from(Instant.now()));
            message.setId(UUID.randomUUID());
    
            return messageService.deliverMessage(message);
        }
    }
    
    @Service
    public class MessageService {
    
        public Message deliverMessage (Message message) {
    
            return message;
        }
    }
    
    
    public class Message {
    
        private String from;
        private String to;
        private String text;
        private Date date;
        private UUID id;
    
        public String getFrom() {
            return from;
        }
    
        public void setFrom(String from) {
            this.from = from;
        }
    
        public String getTo() {
            return to;
        }
    
        public void setTo(String to) {
            this.to = to;
        }
    
        public String getText() {
            return text;
        }
    
        public void setText(String text) {
            this.text = text;
        }
    
        public Date getDate() {
            return date;
        }
    
        public void setDate(Date date) {
            this.date = date;
        }
    
        public UUID getId() {
            return id;
        }
    
        public void setId(UUID id) {
            this.id = id;
        }
    }
    

    假设我们有一个MessageController,它的createMessage方法接受一个MessageDTO,并构造出Message对象,传递给messageService的deliverMessage().
    以下是我们的校验,messageService调用了任何Message对象一次

    verify(messageService, times(1)).deliverMessage(any(Message.class));
    

    使用any匹配器无法校验Message对象内部更多的细节,比如是否和MessageDTO内部封装的data一致。自定义的参数匹配器如下:

    public class MessageMatcher implements ArgumentMatcher<Message> {
     
        private Message left;
     
        // constructors
     
        @Override
        public boolean matches(Message right) {
            return left.getFrom().equals(right.getFrom()) &&
              left.getTo().equals(right.getTo()) &&
              left.getText().equals(right.getText()) &&
              right.getDate() != null &&
              right.getId() != null;
        }
    }
    

    使用自定义参数匹配器时,需要使用argThat,如下:

    verify(messageService, times(1)).deliverMessage(argThat(new MessageMatcher(message)));
    

    现在我们就可以验证传递到messageService.deliverMessageMessage()方法的mesage和MessageDTO包含相同的数据了。

    相关文章

      网友评论

          本文标题:Mockito的参数匹配器

          本文链接:https://www.haomeiwen.com/subject/ahcewqtx.html