Java.nio.file.Filesのように、他のユーティリティクラスに依存するクラスをテストするのは非常に難しいことがわかりました。 powermockのような他の重いモックフレームワークを使用しない限り、クラシックユニットテストスタック(junit、mockito、..)を使用してそれらをモックすることも不可能です。また、mavenプラグイン(surefire、jacoco、オフラインインストルメンテーションなど)と統合しようとすると、悪夢になります。
ユニットテストを簡単にするために私が決めたのは、このユーティリティクラスを通常のインスタンス化可能なクラス内にラップし、次のようにメインクラスに挿入することです。
public class IOManager {
private final FileSystemUtilsWrapper fileSystemUtilsWrapper;
private final HttpUtilsWrapper httpUtilsWrapper;
public IOManager() {
this.fileSystemUtilsWrapper = new FileSystemUtilsWrapper();
this.httpUtilsWrapper = new HttpUtilsWrapper();
}
public IOManager(
FileSystemUtilsWrapper fileSystemUtilsWrapper,
HttpUtilsWrapper httpUtilsWrapper
) {
if (fileSystemUtilsWrapper == null
|| httpUtilsWrapper == null) {
throw new NullPointerException("...");
}
this.fileSystemUtilsWrapper = fileSystemUtilsWrapper;
this.httpUtilsWrapper = httpUtilsWrapper;
}
public boolean doIOOperations(String filePath, String url) throws IOException {
if (fileSystemUtilsWrapper.isMyFileReachable(filePath)
&& httpUtilsWrapper.isMyURLReachable(url)) {
// do something and returns IO state
}
return false;
}
}
/**
* FileSystem utils wrapper
*/
class FileSystemUtilsWrapper {
public boolean isMyFileReachable(String filePath) {
Path path = Paths.get(filePath);
return Files.exists(path) && Files.isWritable(path);
}
}
/**
* http utils wrapper
*/
class HttpUtilsWrapper {
public boolean isMyURLReachable(String url) throws IOException {
HttpURLConnection urlConnection = (HttpURLConnection) new URL(url)
.openConnection()
;
// i keep it simple
return urlConnection.getResponseCode() == 200;
}
}
簡単な洞察を得るために、単純にしています。
SUT内のユーティリティクラスを直接使用し、I/Oリソースを模擬することも検討したことに注意してください(ダミーファイルを作成および削除し、wiremockを使用してhttpエンドポイントを模擬します)。最も簡単な方法のように見えるかもしれませんが、IMOは単体テストではなく統合テストであるため、そうするべきではありません。
私の分析について、あなたの意見を聞いていただければ幸いです。よろしくお願いいたします。
ここで私が気に入っているのは、オーバーライド可能なデフォルト値です。それは良い。ハードコーディングを回避します。テストに関係なくお勧めします。そしてそうしました before 。
IOManager
がラッパーをデフォルト値としてだけでなくタイプとしても使用しているのが好きだと思います。ラッパーを置き換えることを意味するものは、それらから継承する必要があります。ラッパーは具体的ではなく、抽象的です。これが yo-yo問題 の始まりであることを意味します。
その問題からあなたを導くことができる良い原則は 依存関係逆転の原理 です。それはそれを教えています:
ここでインターフェイスを使用する必要があると言っているのではありません。しかし、少なくともFileSystemUtils
およびHttpUtils
という名前の抽象クラスがあり、IOManager
が型として使用できるとしたら、それはいいことです。こうすることで、コードを取得し、HttpsUtilsWrapper
を作成してnew URL(url)
からnew SecureURL(url)
に切り替えるときに、メンテナンスコーダーを使用せずに未使用のコードを確認することはありません。オーバーライドされたコード。