I'm addicted to how to write test code for a class that receives Context in the constructor and uses Context.openFileInput and Context.openFileOutput, so I'll write it down.
BooleanRepository.java
public class BooleanRepository {
static final String FILE_NAME = "BOOLEAN.txt";
@NonNull private final Context context;
public BooleanRepository(@NonNull Context context) { this.context = context; }
public boolean load() throws IOException {
try (final InputStream is = context.openFileInput(FILE_NAME);
final InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8);
final BufferedReader reader = new BufferedReader(isr)) {
return Boolean.valueOf(reader.readLine());
}
}
public void save(boolean bool) throws IOException {
try (final OutputStream os = context.openFileOutput(FILE_NAME, Context.MODE_PRIVATE);
final OutputStreamWriter osw = new OutputStreamWriter(os, StandardCharsets.UTF_8);
final PrintWriter writer = new PrintWriter(osw)) {
writer.append(bool);
}
}
}
build.gradle
android {
compileSdkVersion 28
...
testOptions {
unitTests {
includeAndroidResources = true
}
}
}
dependencies {
testImplementation 'androidx.test:core:1.2.0'
testImplementation 'com.google.truth:truth:0.45'
}
BooleanRepositorySpec.java
@RunWith(RobolectricTestRunner.class)
public class MemoRepositorySpec {
private static final boolean INPUT_BOOL = true;
private static final String INPUT_STRING = String.valueOf(INPUT_BOOL);
private BooleanRepository booleanRepository;
private Context context;
@Before
public void setUp() {
this.context = ApplicationProvider.getApplicationContext();
this.booleanRepository = new BooleanRepository(context);
}
@Test
public void load() throws Exception {
final File file = new File(context.getFilesDir(), BooleanRepository.FILE_NAME);
try (final Writer fileWriter = Files.newBufferedWriter(file.toPath(), StandardCharsets.UTF_8)) {
fileWriter.write(INPUT_STRING);
}
final boolean output = booleanRepository.load();
assertThat(output).isEqualTo(INPUT_BOOL);
}
@Test
public void save() throws Exception {
booleanRepository.save(true);
final File file = new File(context.getFilesDir(), BooleanRepository.FILE_NAME);
try (final FileInputStream fileInputStream = new FileInputStream(file)) {
final byte[] readBuffer = new byte[INPUT_STRING.length()];
fileInputStream.read(readBuffer);
assertThat(readBuffer).isEqualTo(INPUT_STRING);
}
}
}
BufferedReader and PrintWriterWhy not mock the new BufferedReader and PrintWriter in the method with PowerMock first? I thought.
However, I didn't know how to use PowerMock and gave up because I couldn't replace it well.
Context.openFileInput and Context.openFileOutputNext, what if we could mock Context.openFileInput and Context.openFileOutput to return ByteArrayInputStream and ByteArrayOutputStream? I thought.
However, the return values of Context.openFileInput and Context.openFileOutput are FileInputStream and FileOutputStream, respectively, so the return values do not match, so it is impossible.
, ʻOutputStream and mock itCreate a method that returns ʻInputStream, ʻOutputStream,
BooleanRepository.java
InputStream getInputStream() throws FileNotFoundException {
return context.openFileInput(FILE_NAME);
}
OutputStream getOutputStream() throws FileNotFoundException {
return context.openFileOutput(FILE_NAME, Context.MODE_PRIVATE);
}
Change the method under test to read from it.
BooleanRepository.java
try (final InputStream is = getInputStream();
/* ... */
try (final OutputStream os = getOutputStream();
Mock that method with Mockito and return ByteArrayInputStream and ByteArrayOutputStream respectively.
You can pass the byte array of the file contents to the constructor for ByteArrayInputStream.
For ByteArrayOutputStream, you can read the output contents in byte [] by doing.toByteArray ().
BooleanRepositorySpec.java
public class MemoRepositorySpec {
private static final boolean INPUT_BOOL = true;
private static final byte[] INPUT_BYTES = String.valueOf(INPUT_BOOL).getBypes(StandardCharsets.UTF_8);
@Spy
private BooleanRepository booleanRepository;
private Context context;
@Before
public void setUp() {
context = mock(Context.class);
booleanRepository = new BooleanRepository(context);
MockitoAnnotations.initMocks(this);
}
@Test
public void load() throws Exception {
final ByteArrayInputStream is = new ByteArrayInputStream(INPUT_BYTES);
doReturn(is).when(booleanRepository).getInputStream();
final boolean output = booleanRepository.load();
assertThat(output).isEqualTo(INPUT_BOOL);
}
@Test
public void save() throws Exception {
final ByteArrayOutputStream os = new ByteArrayOutputStream();
doReturn(os).when(booleanRepository).getOutputStream();
booleanRepository.save(true);
assertThat(os.toByteArray()).containsExactly(INPUT_BYTES);
}
}
Recommended Posts