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

    return byteToBase64(salt); 
} 

Удивительно, как написать тестовый пример с помощью Junit для этого метода. Любое предложение?Junit test case

+0

Возможный дубликат [Тестирование методом случайного поведения] (http: // stackoverflow.com/questions/3812154/unit-testing-a-method-with-random-behavior) – guerda

+1

@guerda Эта статья касается * того, как бороться со случайностью *. Здесь возникает вопрос: как проверить, генерируется ли произвольное случайное значение? – gaborsch

ответ

0

я могу думать о двух случаях тест -

  • Убедитесь, что возвращение не равно нулю.
  • Убедитесь, что возврат base64, если вы ожидаете, что он будет base64. Хотя не имеет значения, ожидаете ли вы какую-нибудь случайную строку.
3

Прежде всего, новый 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 было бы легко написать. Внедрите посмеянный randomUtil, используя некоторую платформу тестирования, такую ​​как Mockito. Сделайте метод mockedRandomUtil.generateSeed (int) верным фиксированным числом. Ваш тест действительно проверяет, выполняет ли метод byteToBase64() то, что он должен делать. Теперь у вас есть детерминированное число для вашего теста. Вы можете предоставить все виды чисел, которые могут быть созданы SecureRandom в вашем тестовом классе в качестве отдельных тестовых примеров, чтобы проверить результат byteToBase64(). В качестве плюса ваш код генерации случайных чисел теперь отделен от вашего кода base64.

Надеюсь, это помогло.

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); 
} 
+0

Вы можете немного улучшить его, выполнив ряд тестов с 4 значениями. Возможно, что здесь будет 2 равных, но маловероятно, что если вы сделаете 5 из этих 4-значных тестов, более одного вы получите соответствующую пару. – gaborsch

+0

* хмуриться * где вы видите возможность совпадения пар? –

+0

Теоретически он имеет такую ​​же вероятность бросить '6,6,6,6,6,6' с кубиками, чтобы бросить' 1,5,3,2,6,5'. Итак, для этого есть шанс. Вы не можете предсказать, какое значение придет, поэтому оно называется * random *. Таким образом, вы даже ** не можете исключить **, что одни и те же значения появятся в строке. – gaborsch

0

Вы можете проверить 3 вещи:

  1. Если результат является нулевым или не
  2. Если результат соответствует формальным требованиям (это Base64 String)
  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); 
} 
Смежные вопросы