I want to test A
class.
In A class constructor method, a private final dependency d
is created. I want to mock d
. Here is the code
public class A {
public A () throws FileNotFoundException {}
private final D d = new D();
}
public class D {
public D () throws FileNotFoundException {
Reader reader = new InputStreamReader(new FileInputStream("filePath"));
// other code...
}
}
Since the filePath is a special path fitting in the docker config, me and my mentor decided to use MOCK to return a d
to test A
class.
I did not know how to mock this situation. Previously, I did use FieldSetter
in Mockito
to solve simple cases.
The first option would be to declare D
as a constructor argument. This is also called dependency injection and can be useful for testing. Additionally, you can still have a constructor without any arguments:
public class A {
public A (D d) throws FileNotFoundException {
this.d = d;
}
public A () throws FileNotFoundException {
this(new D());
}
private final D d;
}
@Test
void test() {
D mock = mock(D.class);
A tested = new A(mock);
// ...
}
Alternatively, you can test this code even more elegantly, without any mocks. To do so, we need to apply the same technique to D
and use dependency injection for passing a Reader
:
public class D {
public D () throws FileNotFoundException {
this(new InputStreamReader(new FileInputStream("filePath")));
}
public D (Reader reader) throws FileNotFoundException {
// other code...
}
}
Since Reader
is an interface, we can use different implementations for it, inside the test. For instance, we can use a StringReader
:
@Test
void test() {
D d = new D(new StringReader("my test file content"));
A tested = new A(d);
// ...
}