簡體   English   中英

如何從java.util包中模擬UUID.randomUUID()?

[英]How to mock UUID.randomUUID() from java.util package?

UUID.randomUUID()有什么問題 - 它不能被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();
    }
}

一種方法使用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() 如果以后您決定需要使用版本2 UUID(基於日期時間)或其他版本而不是隨機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_指出了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM