ArrayList 上的 isEmpty() 结果为 false,尽管其大小为 0
isEmpty() on an ArrayList results in false although its size is 0
在测试中,我向另一个 class 注入了一个模拟,它似乎工作正常。但是,当我检查 ArrayList 是否为空时,尽管其 length/size 为 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 {
...
}
}
}
这是我的测试 class:
@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);
});
}
}
属性class:
@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 = "";
}
}
‘app’是一个模拟。您必须模拟您使用的任何方法,否则它会检索类型的默认值。
List apps = Mockito.mock(ArrayList.class);
当您模拟一个 class 时,它的所有方法体都将被完全丢弃。具有非 void
return 类型的方法 return 该类型的默认值。 size()
为 0(int
的默认值),但 isEmpty()
为 false
(boolean
的默认值)。
您可以使用 spy
而不是 mock
来获取您不模拟的方法的实际实现。这也是 when(x.method()).thenReturn(y)
和 doReturn(y).when(x).method()
之间的区别所在。前者实际上调用了该方法,但丢弃了它的结果以支持模拟的 return 值。后者根本不调用该方法(但类型不安全)。
你嘲笑数组列表是有原因的吗?我根本没看到你使用数组列表作为模拟。
在测试中,我向另一个 class 注入了一个模拟,它似乎工作正常。但是,当我检查 ArrayList 是否为空时,尽管其 length/size 为 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 {
...
}
}
}
这是我的测试 class:
@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);
});
}
}
属性class:
@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 = "";
}
}
‘app’是一个模拟。您必须模拟您使用的任何方法,否则它会检索类型的默认值。
List apps = Mockito.mock(ArrayList.class);
当您模拟一个 class 时,它的所有方法体都将被完全丢弃。具有非 void
return 类型的方法 return 该类型的默认值。 size()
为 0(int
的默认值),但 isEmpty()
为 false
(boolean
的默认值)。
您可以使用 spy
而不是 mock
来获取您不模拟的方法的实际实现。这也是 when(x.method()).thenReturn(y)
和 doReturn(y).when(x).method()
之间的区别所在。前者实际上调用了该方法,但丢弃了它的结果以支持模拟的 return 值。后者根本不调用该方法(但类型不安全)。
你嘲笑数组列表是有原因的吗?我根本没看到你使用数组列表作为模拟。