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

Mockito测试:void方法第3次调用时抛出RuntimeException的问题

解锁门多次失败锁定逻辑的测试问题

业务代码实现

DoorServiceEjb 服务类

@Stateless(name = "DoorServiceEjb")
public class DoorServiceEjb {
    private static final int EXPIRY_PERIOD = 1;
    private static final int MAX_ATTEMPTS = 3;

    private LoadingCache<String, Integer> attemptsCache;

    public DoorServiceEjb() {
        super();
        attemptsCache = CacheBuilder
            .newBuilder()
            .expireAfterWrite(EXPIRY_PERIOD, TimeUnit.MINUTES)
            .build(new CacheLoader<String, Integer>() {
                       @Override
                       public Integer load(String key) throws Exception {
                           return 0;
                       }
                   }
            );
    }

    public boolean isLockedOut(String key) {
        try {
            boolean returnValue = attemptsCache.get(key) >= MAX_ATTEMPTS;
            return returnValue;
        } catch (ExecutionException e) {
            return false;
        }
    }
}

Door 业务类

public class Door {

    @EJB(beanName = "DoorServiceEjb")
    private DoorServiceEjb doorServiceEjb;

    public void unlock(String user) {
        if (doorServiceEjb.isLockedOut(user)) {
            throw new RuntimeException("Locked");
        }

        // Do something else
    }
}

需求

当用户调用unlock()方法3次及以上时,该方法需抛出带有Locked消息的RuntimeException。

测试方案疑问与问题

我编写了如下测试用例,但不确定是否符合规范。我一直认为断言和验证应该针对@InjectMocks标注的被测对象,@Mock仅用于模拟被测对象的内部依赖。但我的测试中完全未使用@InjectMocks,反而对@Mock标注的Door对象进行验证和断言,且最终断言失败——捕获到的异常消息为null,而非预期的Locked。

测试代码

@ExtendWith(MockitoExtension.class)
public class DoorTest {

    @Mock
    private Door door;

    @Test
    public void test_3FailedUnlockAttempts_ShouldLock() {

        Mockito.doNothing().doNothing().doThrow(RuntimeException.class).when(door).unlock(anyString());

        door.unlock(anyString());
        door.unlock(anyString());

        RuntimeException exception = assertThrows(RuntimeException.class, () -> {
            door.unlock(anyString()); // should throw RuntimeException
        });

        Mockito.verify(door, times(3)).unlock(anyString());
        
        // 断言失败:异常消息为null,而非"Locked"
        Assertions.assertTrue(exception.getMessage().contains("Locked"));
    }
}

内容的提问来源于stack exchange,提问作者pixel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 07:10:27