简体   繁体   English

使用Mockito验证递归方法调用的最佳实践

[英]Best practices for verifying recursive method calls with Mockito

Consider this example class: 考虑以下示例类:

public class Processor {
  private final Dependency dependency;

  public Processor(Dependency dependency) {
    this.dependency = dependency;
  }

  public void processUsers(List<Integer> userIds, int attempt) {
    if (attempt == 0) {
      //log initial processing
    } else if (attempt > 0 && attempt < 5) {
      //log retry processing
    } else {
      //log processing limit exceeded
      return;
    }
    List<Integer> failedIds = new ArrayList<Integer>();
    for (Integer userId : userIds) {
      try {
        processUser(userId);
      } catch (Exception ex) {
        //logging
        failedIds.add(userId);
      }
    }
    if (failedIds.isEmpty()) {
      //log ok
    } else {
      processUsers(failedIds, attempt + 1);
    }
  }

  public void processUser(Integer userId) throws Exception{
    //dependency can throw exception
    dependency.call();
  }
}

I would like to verify that method processUsers calls itself when exception is thrown. 我想验证抛出异常时方法processUsers自行调用。 Here is my testy test: 这是我的测试:

public class ProcessorTest {
  @Test
  public void processShouldCallItselfWithFailedSublistWhenProcessingFails(){
    Dependency dependency = mock(Dependency.class);
    when(dependency.call()).thenThrow(Exception.class);
    Processor processor = new Processor(dependency);
    processor.processUsers(Arrays.asList(new Integer[]{1,2,3}), 0);
    //need to verify processor will call #processUsers recursively
    //because the dependency thrown Exception, how?
  }
}

What are best practices for verifying that method calls itself recursively under certain circumstances? 在某些情况下,递归地验证该方法的最佳实践是什么?

I'm using TestNG + Mockito and this verbose language called JAVA 我正在使用TestNG + Mockito和称为JAVA冗长语言

You can verify the number of times dependency.call() is invoked. 您可以验证dependency.call()被调用的次数。 This would tell you that retry worked - just by the number of calls: 这将告诉您重试有效-仅按呼叫数即可:

@Test
public void processShouldCallItselfWithFailedSublistWhenProcessingFails() {
    Dependency dependency = mock(Dependency.class);
    when(dependency.call()).thenReturn(1, 2).thenThrow(Exception.class).
        thenReturn(4);
    Processor processor = new Processor(dependency);
    processor.processUsers(Arrays.asList(new Integer[]{1, 2, 3}), 0);
    verify(dependency, times(4)).call();
}

This would tell you that retry eventually failed with too many exceptions: 这将告诉您,重试最终因太多异常而失败:

@Test
public void processShouldFailAfterTooManyRetries() {
    Dependency dependency = mock(Dependency.class);
    when(dependency.call()).thenThrow(Exception.class);
    Processor processor = new Processor(dependency);
    final List<Integer> userIds = Arrays.asList(new Integer[]{1, 2, 3});
    final int expectedRetries = 5;
    processor.processUsers(userIds, 0);
    verify(dependency, times(expectedRetries * userIds.size())).call();
}

If the call to dependency actually used the userId, then you could actually check that all the expected calls to dependency.call(int userId) happened. 如果对依赖项的调用实际上使用了userId,则实际上可以检查是否对期望的所有dependency.call(int userId)调用都进行了dependency.call(int userId) This would tell you that it all of them went through given enough retries: 这将告诉您所有这些都经过足够的重试:

@Test
public void processShouldCallItselfWithFailedSublistWhenProcessingFails() {
    Dependency dependency = mock(Dependency.class);
    when(dependency.call(anyInt())).
        thenReturn(1, 2).thenThrow(Exception.class).thenReturn(4);
    Processor processor = new Processor(dependency);
    processor.processUsers(Arrays.asList(new Integer[]{1, 2, 3}), 0);
    verify(dependency).call(1);
    verify(dependency).call(2);
    verify(dependency, times(2)).call(3);
}

@Test
public void processShouldFailAfterTooManyRetries() {
    Dependency dependency = mock(Dependency.class);
    when(dependency.call(anyInt())).thenThrow(Exception.class);
    Processor processor = new Processor(dependency);
    final List<Integer> userIds = Arrays.asList(new Integer[]{1, 2, 3});
    final int expectedRetries = 5;
    processor.processUsers(userIds, 0);
    for (Integer userId : userIds) {
        verify(dependency, times(expectedRetries)).call(userId);
    }
}

Not sure about best practices but you can achieve same by verifying number of times the method is invoked 不确定最佳做法,但是可以通过验证方法的调用次数来实现最佳做法

 int invocationCount = 5; // Or any other desired number
 verify(processor,times(invocationCount)).processUsers();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM