我已经使下面的JUnit 5/Mockito测试代码成为一个简单的自包含复制和粘贴;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.s3.model.S3ObjectInputStream;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Builder;
import lombok.Data;
import org.apache.http.client.methods.HttpRequestBase;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.stream.Collectors;
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.WARN)
public class S3GetObjectContentTest {
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
@Mock private HttpRequestBase httpRequestBase;
@Mock private S3Object s3Object;
private final LinkedHashSet<Pet> s3FileContents = new LinkedHashSet<>();
@BeforeEach
void setup() throws IOException {
s3FileContents.clear();
s3FileContents.addAll(
List.of(
Pet.builder().name("Jerry").type("mouse").build(),
Pet.builder().name("Tom").type("cat").build(),
Pet.builder().name("Roger").type("bunny").build()));
Mockito.when(s3Object.getObjectContent())
.thenReturn(
new S3ObjectInputStream(
new ByteArrayInputStream(OBJECT_MAPPER.writeValueAsBytes(s3FileContents)),
httpRequestBase));
}
@Test
public void doTest() {
for(int n=0; n < 3; n++){
try (final InputStreamReader streamReader =
new InputStreamReader(s3Object.getObjectContent(), StandardCharsets.UTF_8);
final BufferedReader reader = new BufferedReader(streamReader)) {
String text = reader.lines().collect(Collectors.joining());
System.out.println("reader-content: "+ (text.isEmpty() ? "\"\"" : text));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
@Data
@Builder
public static class Pet {
public final String name;
public final String type;
}
}
字符串
- 当运行上述测试代码时,预期输出如下:***
reader-content: [{"name":"Jerry","type":"mouse"},{"name":"Tom","type":"cat"},{"name":"Roger","type":"bunny"}]
reader-content: [{"name":"Jerry","type":"mouse"},{"name":"Tom","type":"cat"},{"name":"Roger","type":"bunny"}]
reader-content: [{"name":"Jerry","type":"mouse"},{"name":"Tom","type":"cat"},{"name":"Roger","type":"bunny"}]
型
- 但实际输出为;***
reader-content: [{"name":"Jerry","type":"mouse"},{"name":"Tom","type":"cat"},{"name":"Roger","type":"bunny"}]
reader-content: ""
reader-content: ""
型
问题:
为什么s3Object.getObjectContent()
的Mock只在第一次调用时启动,然后吐空?
注:
在实验上 (从来都不理想),我观察到,只有当我把mock放在for...loop
里面时,我才能得到预期的结果...假设这可能只是给予一些额外的上下文
@Test
public void doTest() throws JsonProcessingException {
for(int n=0; n < 3; n++){
// ========================== Experimental (Not practical) ==========================
Mockito.when(s3Object.getObjectContent())
.thenReturn(
new S3ObjectInputStream(
new ByteArrayInputStream(OBJECT_MAPPER.writeValueAsBytes(s3FileContents)),
httpRequestBase));
// ==================================================================================
try (final InputStreamReader streamReader =
new InputStreamReader(s3Object.getObjectContent(), StandardCharsets.UTF_8);
final BufferedReader reader = new BufferedReader(streamReader)) {
String text = reader.lines().collect(Collectors.joining());
System.out.println("reader-content: "+ (text.isEmpty() ? "\"\"" : text));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
型
2条答案
按热度按时间a64a0gku1#
我怀疑在第一次运行后,流被关闭,所以你不能从中获得更多的数据。beforeEach方法只运行一次,而不是三次。您可以通过将“when”语句从setup方法移到for循环中来解决这个问题。
sqyvllje2#
好吧,事实证明解决方案并不是离家很远。😊
只需根据调用模拟
s3Object.getObjectContent()
,如下所示;字符串
向 Tofig Hasanov 大喊,因为他的快速洞察力帮助我解决了这个问题。