UUID.randomUUID()
の何が問題になっているのですか-あざけることができません
モックすることは可能ですか?または、ソースにエラーがありますか?
例を見てください:
1)テストされるクラス
package com.grayen;
import Java.util.UUID;
public class TestedClass {
public UUID getUuid() {
return UUID.randomUUID();
}
public UUID getUuidFromWrapper() {
return UuidWrapper.randomUUID();
}
}
1つの方法は、UUIDのラッパーを使用し、そのラッパーをモックできます!
2)実際のUUIDのラッパー(すべての修飾子は同じ)
package com.grayen;
import Java.util.UUID;
public final class UuidWrapper {
public static UUID randomUUID() {
return UUID.randomUUID();
}
}
3)テスト(最後にコメントされた行で例外がスローされます)
package com.grayen;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import Java.util.UUID;
import static org.junit.Assert.assertEquals;
@PrepareForTest({UUID.class, UuidWrapper.class})
@RunWith(PowerMockRunner.class)
public class TestedClassTest {
@Test
public void testMethod() {
UUID uuid = UUID.randomUUID();
PowerMockito.mockStatic(UUID.class);
PowerMockito.mockStatic(UuidWrapper.class);
PowerMockito.when(UUID.randomUUID()).thenReturn(uuid);
PowerMockito.when(UuidWrapper.randomUUID()).thenReturn(uuid);
TestedClass testedClass = new TestedClass();
assertEquals(uuid, testedClass.getUuidFromWrapper());
//assertEquals(uuid, testedClass.getUuid());
}
}
静的メソッドのモックは常に脆弱なアプローチです。可能であれば、静的でないUUIDソースを使用することをお勧めします。これにより、簡単にモックを作成できます。
例えば:
_/**
* A source of new {@link UUID} instances.
*/
public interface UuidSource {
/**
* Returns a new {@link UuidSource} that generates UUIDs using {@link UUID#randomUUID}.
*/
public static UuidSource random() {
return UUID::randomUUID;
}
/**
* Returns a new {@link UUID} instance.
*
* <p>The returned value is guaranteed to be unique.
*/
UUID newUuid();
}
_
次に、それをTestedClass
に注入するか、TestedClass
にプライベートメンバーを含めることができます。
_public class TestedClass {
private UuidSource uuidSource = UuidSource.random();
public UUID getUUID() {
return uuidSource.newUuid();
}
// etc.
}
_
次に、それをテストするには、モックされたUuidSource
に注入できるように、テスト専用コンストラクターを用意するか、uuidSource
フィールドの値を直接置き換えます(可視性を拡大することにより)または反射または何かを使用して)。
おまけとして、これは実際の製品コードをUUID.randomUUID()
から切り離します。後で、ランダムなUUIDではなく、バージョン2のUUID(日時ベース)または他のバージョンを使用する必要があると判断した場合は、プロダクションコードでも簡単に変更できます。これは、コードをよりテストしやすくすることで通常、全体的なデザインが改善されると人々が言っていることを意味しています。
だから私はあなたのコードを取り、それを動作させました。 TestedClass.class
を@PrepareForTest
に追加するだけです。
package com.grayen;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import Java.util.UUID;
import static org.junit.Assert.assertEquals;
@PrepareForTest({
UUID.class,
UuidWrapper.class,
TestedClass.class
})
@RunWith(PowerMockRunner.class)
public class TestedClassTest {
@Test
public void testMethod() {
UUID uuid = UUID.randomUUID();
PowerMockito.mockStatic(UUID.class);
PowerMockito.mockStatic(UuidWrapper.class);
PowerMockito.when(UUID.randomUUID()).thenReturn(uuid);
PowerMockito.when(UuidWrapper.randomUUID()).thenReturn(uuid);
TestedClass testedClass = new TestedClass();
assertEquals(uuid, testedClass.getUuidFromWrapper());
assertEquals(uuid, testedClass.getUuid());
}
}
編集
私はコメントを見ませんでした、しかし k5 _ はそれを指摘しました。