如何用Mockito测试嵌套循环中每条电话号码的DynamoDB.update调用?
用Mockito验证DynamoDB.update的调用情况
首先需要明确几个前提,并对代码做微小调整以适配测试:
- 原方法中参数
aggregateList未被使用,循环依赖的peopleList来源不明,这里假设实际逻辑是从aggregateList中提取人员集合; - 直接调用静态
DynamoDB.update不利于测试,建议将DynamoDB作为依赖注入到待测试类中(比如通过构造函数),而非使用静态方法。
步骤1:改造待测试类
调整依赖注入方式,同时修正参数未使用的问题:
public class PersonService { private final DynamoDB dynamoDB; // 构造函数注入DynamoDB依赖 public PersonService(DynamoDB dynamoDB) { this.dynamoDB = dynamoDB; } public Void getPeopleNumbersList(List<Aggregate<Person>> aggregateList) { // 从aggregateList中提取人员列表,修正原代码的逻辑漏洞 for (Aggregate<Person> aggregate : aggregateList) { List<Person> personList = aggregate.getPersons(); // 假设Aggregate类提供该方法 for (Person person : personList) { List<PhoneNumber> phoneNumbersList = getPhoneNumbers(person); for (PhoneNumber phoneNumber : phoneNumbersList) { dynamoDB.update(phoneNumber); } } } return null; } // 若该方法为类内方法,测试时可通过spy mock返回值 protected List<PhoneNumber> getPhoneNumbers(Person person) { // 实际业务逻辑 return new ArrayList<>(); } }
步骤2:编写JUnit+Mockito测试用例
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; import java.util.List; import static org.mockito.Mockito.*; @ExtendWith(MockitoExtension.class) public class PersonServiceTest { // Mock DynamoDB实例,用于捕获方法调用 @Mock private DynamoDB dynamoDB; // Spy待测试类,实现部分mock(保留原逻辑,仅mock指定方法) @Spy @InjectMocks private PersonService personService; @Test void verifyAllPhoneNumbersAreUpdated() { // 1. 准备测试数据 Person person1 = new Person(); PhoneNumber pn1 = new PhoneNumber("123456"); PhoneNumber pn2 = new PhoneNumber("789012"); Person person2 = new Person(); PhoneNumber pn3 = new PhoneNumber("345678"); Aggregate<Person> aggregate = mock(Aggregate.class); when(aggregate.getPersons()).thenReturn(List.of(person1, person2)); // 2. Mock getPhoneNumbers的返回值,指定每个Person对应的电话号码列表 doReturn(List.of(pn1, pn2)).when(personService).getPhoneNumbers(person1); doReturn(List.of(pn3)).when(personService).getPhoneNumbers(person2); // 3. 执行待测试方法 personService.getPeopleNumbersList(List.of(aggregate)); // 4. 验证每个电话号码都被传入update方法 verify(dynamoDB).update(pn1); verify(dynamoDB).update(pn2); verify(dynamoDB).update(pn3); // 可选:验证update方法总调用次数,确保无遗漏或重复 verify(dynamoDB, times(3)).update(any(PhoneNumber.class)); } }
关键说明
- 使用
@Mock创建DynamoDB的mock实例,捕获其方法调用行为; - 使用
@Spy实现待测试类的部分mock,既能保留原类核心逻辑,又能灵活mockgetPhoneNumbers这类辅助方法的返回值; - 通过
verify逐一验证每个PhoneNumber对象都被正确传入update方法,确保所有电话号码都被处理; - 额外的
times(3)验证可确认调用次数符合预期,避免漏处理或重复操作。
内容的提问来源于stack exchange,提问作者Ronnie
相关产品推荐
相关产品推荐

