Search code examples
scalascalatest

Replace a method for usage only in a particular unit tests in Scala


Is it possible to replace a method only used in a particular unit tests in Scala using version 2.11 and scalatest 3.0.4?

This is my scenraio: I have the method

import java.security.SecureRandom
import org.bouncycastle.util.encoders.Hex

class KeyHasher extends Serializable {

  // getSalt returns a random number that servers as salt for the actual hash algorithm  
  def getSalt(length): String = {
    val salt: Array[Byte] = new Array[Byte](length)
    secureRandom.nextBytes(salt)
    Hex.toHexString(hashedKey)
  }

  def getEncodedKey(actualKey: String): String = {
  ...
  val salt = getSalt() 
  ...
  return applyHash(salt) // apply a hash algorithm using a salt
  }

}

For a particular unit test I would like to ensure that the method getSalt returns a constant, not random number.

I know, I could use an additional input Parameter (testFlag) in the getEncodedKey method or a global variable in the getSalt method to get a solution for this. However, I wanted to know if there is a way do not touch the getEncodedKey and only implement something in one unit test.


Solution

  • A simple approach is to just create a trait like SaltGenerator and then, implement the one used by your method, this will allow you to create a SatlGenerator which returns a constant while testing.

    For example:

    trait SaltGenerator {
      def getSalt(length): String
    }
    
    class KeyHasher(saltGenerator: SaltGenerator) {...}
    

    Then, while writing your test, just create the generator that returns a constant:

    val saltGenerator = new SaltGenerator {
      def getSalt(length): String = ???
    }
    

    While you may be able to find a way to mock an existing method, that is always tricky and is hard to maintain. If you don't want to update your code, another way is to receive the SecureRandom as a constructor argument but that won't be that simple on the test side to accomplish what you want.