4
public static String generateSaltString() {
    SecureRandom random = new SecureRandom();
    byte[] salt = random.generateSeed(12);

    return byteToBase64(salt);
}

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

4

4 回答 4

3

首先是 new SecureRandom() 可能会非常慢,因此您可能需要缓存它。看看这个答案和这个答案。

我会重构你的代码如下

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 代码分离。

希望它有所帮助。

于 2013-04-16T07:03:22.830 回答
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 的评论,我认为测试的实现有点模糊,因为有可能 - 尽管不太可能 - 函数的两次调用将生成相同的盐:

@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);
}
于 2013-04-16T07:38:07.427 回答
0

我可以想到两个测试用例 -

  • 检查返回不为空。
  • 如果您期望它是 base64,请检查返回是 base64。尽管您是否期望任何随机字符串都没有关系。
于 2013-04-16T04:53:54.650 回答
0

您可以检查 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);
}
于 2013-04-16T22:36:00.957 回答