ArrayList 上的 isEmpty() 结果为 false,尽管其大小为 0

du-*_*-it 0 java arraylist is-empty

在测试中,我向另一个类注入了一个模拟,该类似乎工作正常。但是,当我检查 ArrayList 是否为空时,尽管其长度/大小为 0,结果却为 false。这种情况怎么会发生以及如何解决这个问题?

@Slf4j
@Configuration
@RequiredArgsConstructor
@Setter(onMethod_ = @SuppressFBWarnings({"EI_EXPOSE_REP2", "EI_EXPOSE_REP"}))
@Getter(onMethod_ = @SuppressFBWarnings({"EI_EXPOSE_REP2", "EI_EXPOSE_REP"}))
@EnableConfigurationProperties(MyProperties.class)
public class MyConfig {

    private final MyProperties myProperties;

    private final GenericApplicationContext applicationContext;

    @PostConstruct
    void init() {
        Objects.requireNonNull(myProperties, "myProperties needs not to be null.");
        if (/*myProperties.getApps().size() == 0 || */myProperties.getApps().isEmpty()) {
            log.info("bla bla bla");
        } else {
            ...
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的测试课:

@ExtendWith(MockitoExtension.class)
class MyConfigTest {

    @Mock
    MyProperties myPropertiesMock;

    @InjectMocks
    MyConfig myConfig;

    ApplicationContextRunner contextRunner;

    @Test
    void should_check_for_empty_apps() {
        contextRunner = new ApplicationContextRunner()
            .withPropertyValues("foobar.apps[0].name=", "foobar.apps[0].baseUrl=", "foobar.apps[0].basePath=")
        ;

        List apps = Mockito.mock(ArrayList.class);
        when(myPropertiesMock.getApps()).thenReturn(apps);

        myConfig.init();

        contextRunner.run(context -> {
            assertThat(apps.size()).isEqualTo(0);
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

属性类:

@Slf4j
@Validated
@Data
@Setter(onMethod_ = @SuppressFBWarnings({"EI_EXPOSE_REP2", "EI_EXPOSE_REP"}))
@Getter(onMethod_ = @SuppressFBWarnings({"EI_EXPOSE_REP2", "EI_EXPOSE_REP"}))
@ConfigurationProperties(prefix = MyProperties.CONFIG_PREFIX)
public class MyProperties implements LoggableProperties {

    public static final String CONFIG_PREFIX = "foobar";

    @Valid
    @NestedConfigurationProperty
    private List<MyEndpoint> apps = new ArrayList<>();

    @Data
    public static class MyEndpoint {
//        @NotNull
//        @NotEmpty
        private String baseUrl = "";

        private String basePath = "";

//        @NotNull
//        @NotEmpty
        private String name = "";
    }
}
Run Code Online (Sandbox Code Playgroud)

Rob*_*oor 5

List apps = Mockito.mock(ArrayList.class);
Run Code Online (Sandbox Code Playgroud)

当您模拟一个类时,它的所有方法体都将被完全丢弃。具有非返回类型的方法void返回该类型的默认值。对于size()that 是 0(默认为int),但对于isEmpty()that 是false(默认为boolean)。

您可以使用spy而不是mock获取您不模拟的方法的实际实现。这也是when(x.method()).thenReturn(y)doReturn(y).when(x).method()不同的地方。前者实际上调用该方法,但放弃其结果,转而使用模拟的返回值。后者根本不调用该方法(但不是类型安全的)。

您嘲笑数组列表有什么原因吗?我根本没有看到您使用数组列表作为模拟。