How to use a String like it’s a File in Scala (such as in testing)

This is an excerpt from the Scala Cookbook. This is Recipe 12.7, “How to use a String like it's a file in Scala.”

Problem

Typically for the purposes of testing, you want to pretend that a String is a file in your Scala code.

Solution

Because Scala.fromFile and Scala.fromString both extend scala.io.Source, they are easily interchangeable. As long as your method takes a Source reference, you can pass it the BufferedSource you get from calling Source.fromFile, or the Source you get from calling Source.fromString.

For example, the following method takes a Source object and prints the lines it contains:

import io.Source

def printLines(source: Source) {
    for (line <- source.getLines) {
        println(line)
    }
}

It can be called when the source is constructed from a String:

val s = Source.fromString("foo\nbar\n")
printLines(s)

It can also be called when the source is a file:

val f = Source.fromFile("/Users/Al/.bash_profile")
printLines(f)

Discussion

When writing unit tests, you might have a method like this that you’d like to test:

package foo

object FileUtils {
    def getLinesUppercased(source: io.Source): List[String] = {
        (for (line <- source.getLines) yield line.toUpperCase).toList
    }
}

As shown in the following ScalaTest tests, you can test the getLinesUppercased method by passing it either a Source from a file or a String:

package foo

import org.scalatest.{FunSuite, BeforeAndAfter}
import scala.io.Source

class FileUtilTests extends FunSuite with BeforeAndAfter {
    var source: Source = _

    after { source.close }

    // assumes the file has the string "foo" as its first line
    test("1 - foo file") {
        source = Source.fromFile("/Users/Al/tmp/foo")
        val lines = FileUtils.getLinesUppercased(source)
        assert(lines(0) == "FOO")
    }

    test("2 - foo string") {
        source = Source.fromString("foo\n")
        val lines = FileUtils.getLinesUppercased(source)
        assert(lines(0) == "FOO")
    }

}

In summary, if you’re interested in making your method easily testable with a String instead of a file, define your method to take a Source instance.

See Also

The Scala Cookbook

This tutorial is sponsored by the Scala Cookbook, which I wrote for O’Reilly:

You can find the Scala Cookbook at these locations:

Add new comment

The content of this field is kept private and will not be shown publicly.

Anonymous format

  • Allowed HTML tags: <em> <strong> <cite> <code> <ul type> <ol start type> <li> <pre>
  • Lines and paragraphs break automatically.
By submitting this form, you accept the Mollom privacy policy.