クラスに多数の静的メソッドが含まれている場合、誰もこのクラスのインスタンスを誤って初期化しないようにするために、プライベート コンストラクターを作成しました。
private Utils() {
}
さて..コンストラクターが見えない場合、これをどのようにテストできますか? これはテストでカバーできますか?
クラスに多数の静的メソッドが含まれている場合、誰もこのクラスのインスタンスを誤って初期化しないようにするために、プライベート コンストラクターを作成しました。
private Utils() {
}
さて..コンストラクターが見えない場合、これをどのようにテストできますか? これはテストでカバーできますか?
リフレクションを使用すると、プライベートコンストラクターを呼び出すことができます。
Constructor<Util> c = Utils.class.getDeclaredConstructor();
c.setAccessible(true);
Utils u = c.newInstance(); // Hello sailor
ただし、それでも不可能にすることができます。
private Utils() {
throw new UnsupportedOperationException();
}
コンストラクターで例外をスローすることにより、すべての試行を防ぎます。
私もクラス自体を作成しfinal
ます。「理由」:
public final class Utils {
private Utils() {
throw new UnsupportedOperationException();
}
}
コードの意図をテストしてください..常に:)
例: コンストラクターが非公開であることのポイントが見られない場合、テストする必要があるのはこの事実であり、他には何もありません。
リフレクションAPIを使用してコンストラクターを照会し、プライベート属性が設定されていることを検証します。
私はこのようなことをします:
@Test()
public void testPrivateConstructors() {
final Constructor<?>[] constructors = Utils.class.getDeclaredConstructors();
for (Constructor<?> constructor : constructors) {
assertTrue(Modifier.isPrivate(constructor.getModifiers()));
}
}
オブジェクトの構築を適切にテストしたい場合は、構築されたオブジェクトを取得できるパブリック API をテストする必要があります。それが、前述の API が存在する必要がある理由です。オブジェクトを適切に構築するため、そのためにテストする必要があります :)。
@Test
public//
void privateConstructorTest() throws Exception {
final Constructor<?>[] constructors = Utils.class.getDeclaredConstructors();
// check that all constructors are 'private':
for (final Constructor<?> constructor : constructors) {
Assert.assertTrue(Modifier.isPrivate(constructor.getModifiers()));
}
// call the private constructor:
constructors[0].setAccessible(true);
constructors[0].newInstance((Object[]) null);
}
誰もこのクラスのインスタンスを誤って初期化しないようにするため
通常、私が行うことは、メソッド/コンストラクターをプライベートからデフォルトのパッケージの可視性に変更することです。また、テストクラスに同じパッケージを使用しているため、外部からではなくても、テストからメソッド/コンストラクターにアクセスできます。
クラスをインスタンス化しないようにポリシーを適用するには、次のことができます。
テストがターゲット クラスと同じパッケージを共有している場合は、コンストラクターをサブクラス化して実行できます。これはかなり「エラープルーフ」である必要があります。悪意のあるコーダーは常に回避策を見つけます:)
プライベート コンストラクターがある場合は、コードのプライベートではないメソッドから呼び出されます。したがって、そのメソッドをテストすると、コンストラクターがカバーされます。メソッドごとにテストを行うことに宗教的な美徳はありません。関数またはブランチ カバレッジ レベルを探している場合、コンストラクターを使用するコード パスを介してコンストラクターを実行するだけで、それを取得できます。
そのコード パスが複雑でテストが難しい場合は、リファクタリングが必要になる可能性があります。
次のようなコンストラクターに例外を追加する場合:
private Utils() {
throw new UnsupportedOperationException();
}
constructor.newInstance()
テスト クラスで を呼び出すと、InvocationTargetException
代わりに がスローされますUnsupportedOperationException
が、必要な例外はスローされた例外に含まれます。
例外のスローをアサートしたい場合は、呼び出し例外がキャッチされると、呼び出し例外のターゲットをスローできます。
たとえば、jUnit 4 を使用すると、次のことができます。
@Test(expected = UnsupportedOperationException.class)
public void utilityClassTest() throws NoSuchMethodException, IllegalAccessException, InstantiationException {
final Constructor<Utils> constructor = Utils.class.getDeclaredConstructor();
constructor.setAccessible(true);
try {
constructor.newInstance();
} catch (InvocationTargetException e) {
throw (UnsupportedOperationException) e.getTargetException();
}
}