You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 04:12:10