为了账号安全,请及时绑定邮箱和手机立即绑定

如何从 java.util 包模拟 UUID.randomUUID()?

如何从 java.util 包模拟 UUID.randomUUID()?

慕码人2483693 2021-09-03 14:40:16
有什么问题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());    }}
查看完整描述

2 回答

?
扬帆大鱼

TA贡献1799条经验 获得超9个赞

模拟静态方法始终是一种脆弱的方法。如果可能,最好使用非静态 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,您也可以在生产代码中轻松更改它。这就是人们所说的使您的代码更具可测试性通常会导致更好的整体设计的意思。


查看完整回答
反对 回复 2021-09-03
?
森栏

TA贡献1810条经验 获得超5个赞

所以我拿了你的代码并让它工作。您需要做的就是添加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_指出了它。


查看完整回答
反对 回复 2021-09-03
  • 2 回答
  • 0 关注
  • 274 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信