user2891462 user2891462 - 4 months ago 37
Java Question

Unit testing of encrypt/decrypt

I have implemented a very simple class called

Enigma
which has a symmetric key and two methods:
byte[] encryptString(String strToEncrypt)
and
String decryptBytes(byte[] arrayToDecrypt)
.

I am trying to write some tests for the methods. I have thought of testing that the encrypt and decrypt methods are the inverse of each other, but that says nothing about each of them individually. I wanted to use the methods as they are now to obtain a battery of input-outputs and set that as the tests (I know that is not ideal, but the purpose of these tests is to guarantee that the function behaves in the future as it does today, not that the encryption/decryption are good).

However, I do not know how to obtain a representation of the byte array output by
byte[] encryptString(String strToEncrypt)
so that I can hardcode it in the test class.

Any ideas?

Answer

A few notes on how to test this ( personal opinion warning :-) )

  • If you're writing unit tests, avoid reading expected results from files, since it slows down the test (unit tests have to be super fast), as well as create another thing irrelevant to your code that might go wrong (i.e. the file might be deleted, etc.)
  • Don't use the same method you're testing to created the expected results with which you check the method. This is pointless if you're trying to check the algorithm, and might perpetuate bugs in the algorithm
  • Consider the fact that the smallest unit of work in Java is a class, not a method (forget for a second about Java 8's lambda expressions, you won't really write unit tests for those directly), therefore, you should attempt to test the class, not the methods

My last point there brings me (finally ?) to a recommendation. Think about what's the responsibility of the class (hopefully, the single responsibility, see SRP). In this case, I believe that the responsibility of your class is two way encryption of strings.
Therefore, I would write the following tests:

@Test
public void testThatEncryptingStringResultsInExpectedBytes() {
    byte[] encryption = enigma.encryptString(TEST_STRING);

    assertArrayEquals(EXPECTED_ENCRYPTION, encryption);
}

@Test
public void testThatDecryptinEncryptionResultsInOriginalString() {
    String decryption = enigma.decryptBytes(TEST_ENCRYPTION);

    assertEquals(EXPECTED_ORIGINAL_STRING, decryption);
}

@Test
public void testThatDecriptionReversesEncryption() {
    String decryption = enigma.decryptBytes(enigma.encryptString(TEST_STRING));

    assertEquals(TEST_STRING, decryption);
}

@Test
public void testThatEncryptionReversesDecryption() {
    byte[] encryption = enigma.encriptString(enigma.decryptBytes(TEST_ENCRYPTION));

    assertEquals(TEST_ENCRYPTION, encryption);
}

Maybe add some more tests to check that trying to encrypt/decrypt invalid values throws exceptions, and other error cases.

Comments