【问题标题】:Junit test caseJunit 测试用例
【发布时间】:2013-04-08 07:45:21
【问题描述】:
public static String generateSaltString() {
    SecureRandom random = new SecureRandom();
    byte[] salt = random.generateSeed(12);

    return byteToBase64(salt);
}

想知道如何使用 Junit 为这种方法编写测试用例。 有什么建议吗?

【问题讨论】:

标签: java junit salt


【解决方案1】:

我会测试结果是否不为空,然后多次调用该方法并比较结果以表明每次调用都返回不同的值。

但请记住:这并不能说明结果的随机性质量!

@Test
public void testGenerateSaltString() {
    String salt1 = YourClass.generateSaltString();
    String salt2 = YourClass.generateSaltString();
    String salt3 = YourClass.generateSaltString();
    String salt4 = YourClass.generateSaltString();

    assertNotNull(salt1);
    assertNotNull(salt2);
    assertNotNull(salt3);
    assertNotNull(salt4);

    assertNotEqual(salt1, salt2);
    assertNotEqual(salt1, salt3);
    assertNotEqual(salt1, salt4);

    assertNotEqual(salt2, salt3);
    assertNotEqual(salt2, salt4);

    assertNotEqual(salt3, salt4);
}

考虑到 GaborSch 的 cmets,我想到了一个有点模糊的测试实现,因为有可能 - 尽管不太可能 - 函数的两次调用将生成相同的 salt:

@Test
public void testGenerateSaltString() {
    String salt1;
    String salt2;
    int differenceCount = 0;

    for(int i = 0; i < 1000; i++ ) {
        String salt1 = YourClass.generateSaltString();
        String salt2 = YourClass.generateSaltString();

        // null is still inacceptable
        assertNotNull(salt1);
        assertNotNull(salt2);

        if(!salt1.equalsIgnoreCase(salt2)) {
            differenceCount++;
        }
    }

    // check if at least at 95% of all tries resultet in different strings
    // change this value according to your needs
    assertTrue(differenceCount >= 950);
}

【讨论】:

  • 您可以稍微改进一下,进行一系列 4 值测试。这里可能会有 2 个相等,但如果您执行 5 个这个 4 值测试,则不太可能产生多个匹配对。
  • 皱眉你在哪里看到配对的可能性?
  • 理论上,用骰子掷出6,6,6,6,6,6 的几率与掷出1,5,3,2,6,5 的几率相同。所以,这是有机会的。你无法预测,即将到来的价值是什么,这就是为什么它被称为random。因此,您甚至不能排除相同的值会连续出现。
  • 啊,好吧,你的意思是匹配结果。以为你的意思是我忘记了平等检查。但我明白你的意思。这就是为什么我正在寻找一些关于如何“测试”随机性的建议的原因之一
  • 只有概率。您可以为给定方法是随机的事件提供置信范围。有时会抛出 6 次相同的值,两次都抛出 6000 次的可能性非常。因此,给定一个结果,您可以决定该函数是否产生随机。
【解决方案2】:

您可以检查 3 件事:

  1. 结果是否为空
  2. 如果结果符合形式要求(是Base64字符串)
  3. 如果结果足够随机

例如,以下代码可以工作。我生成了 100 种不同的随机盐,并且它们之间最多允许 1 次匹配。

@Test
public void testGenerateSaltString() {

    Set<String> salts = new HashSet<String>();
    int countSame = 0;
    BASE64Decoder decoder = new BASE64Decoder();

    for(int i=0; i<100; i++) {
        String salt = YourClass.generateSaltString();
        assertNotNull(salt);
        try {
            decoder.decodeBuffer(encodedBytes);
       } catch (Exception e) {
           fail("Not Base64");
       }
       if (salts.contains(salt)) {
            sameCount++;
       }
       salts.add(salt);
    }

    assertTrue(countSame <= 1);
}

【讨论】:

    【解决方案3】:

    第一件事是 new SecureRandom() 可能非常慢,因此您可能需要缓存它。 看看this 的回答和this 也有一个。

    我会重构你的代码如下

    public class DoRandomStuff {
    
    private RandomUtil randomUtil;
    
    public DoRandomStuff(RandomUtil randomUtil) {
        this.randomUtil = randomUtil;
    }
    
    public String generateSaltString() {
        byte[] salt = randomUtil.generateSeed(12);
        return byteToBase64(salt);
    }
    
    public String byteToBase64(byte[] salt) {
        // Do salt generation logic here
        return null;
    }
    

    generateSeed 看起来像一个实用方法调用,因此它可以进入一个看起来像这样的类 RandomUtil

    class RandomUtil {
        private SecureRandom random = new SecureRandom();
        public byte[] generateSeed(int seed) {
            return random.generateSeed(seed);
        }
    }
    

    现在您的 DoRandomStuff 测试类将很容易编写。使用 Mockito 等测试框架注入模拟的 randomUtil。使 mockedRandomUtil.generateSeed(int) 方法返回一个固定数字。您的测试实际上是为了检查 byteToBase64() 方法是否正在做它应该做的事情。现在,您的测试用例有了一个确定的数字。您可以将 SecureRandom 在您的测试类中生成的各种数字作为单独的测试用例提供,以检查 byteToBase64() 结果。 另外,您的随机数生成代码现在与您的 base64 代码分离。

    希望对您有所帮助。

    【讨论】:

      【解决方案4】:

      我能想到两个测试用例-

      • 检查返回值不为空。
      • 如果您期望返回是 base64,请检查返回是 base64。尽管您是否期望任何随机字符串都没有关系。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-29
        • 2020-03-20
        • 2023-03-30
        • 1970-01-01
        相关资源
        最近更新 更多