7
votes

I am starting a new project using Scala and Akka and am having trouble writing tests. In my tests I am checking the equality of two List objects using should equal:

actualBook should equal (expectedBook)

Everything in my test suite compiles and runs, but the tests fail with the following message:

org.scalatest.exceptions.TestFailedException: List(BookRow(A,100.0,10.6)) did not equal List(BookRow(A,100.0,10.6))

Clearly the tests are passing (i.e., both List objects contain the same contents). Not sure if this is relevant or not, but actualBook and expectedBook have the same hash code (and actualBook(0) and expectedBook(0) also have the same hash code).

I am wondering if the problem is due to...

  1. my using the incorrect comparison operator
  2. the fact that I have not explicitly defined a way to compare BookRow objects.

For reference here is the code for my tests:

package lob

import cucumber.api.DataTable
import org.scalatest.Matchers._
import scala.collection.JavaConversions._
import cucumber.api.java.en.{When, Then}

class OrderBookSteps {

  val orderTypes = OrderType.all()

  val buyBook: OrderBook = new OrderBook(Bid, orderTypes)

  val sellBook: OrderBook = new OrderBook(Ask, orderTypes)

  @When("""^the following orders are added to the "(.*?)" book:$""")
  def ordersAddedToBook(sideString: String, orderTable: DataTable) {

    val (side, book) = getBook(sideString)

    val orders = orderTable.asList[OrderRow](classOf[OrderRow]).toList.map(
  r => LimitOrder(r.broker, side, r.volume, r.price.toDouble))
    orders.foreach(book.add)
  }

  @Then("""^the "(.*?)" order book looks like:$""")
  def orderBookLooksLike(sideString: String, bookTable: DataTable) {

    val (_, book) = getBook(sideString)
    val expectedBook = bookTable.asList[BookRow](classOf[BookRow]).toList
    val actualBook = book.orders().map(o => BookRow(o.broker, o.volume, orderTypes(o).bookDisplay))

    actualBook should equal (expectedBook)
  }

  def getBook(side: String) = side match {
    case "Bid" => (Bid, buyBook)
    case "Ask" => (Ask, sellBook)
  }

  case class OrderRow(broker: String, volume: Double, price: String)

  case class BookRow(broker: String, volume: Double, price: String)

}
2

2 Answers

8
votes

You can try:

List(BookRow(A,100.0,10.6)).toSeq should equal (List(BookRow(A,100.0,10.6)).toSeq)

Or:

List(BookRow(A,100.0,10.6) should contain theSameElementsAs List(BookRow(A,100.0,10.6))

Assuming you have BookRow (normal class) equals overridden.

2
votes

I have found a solution, although I don't understand why it works! I just needed to replace:

case class OrderRow(broker: String, volume: Double, price: String)

case class BookRow(broker: String, volume: Double, price: String)

with

private case class OrderRow(broker: String, volume: Double, price: String)

private case class BookRow(broker: String, volume: Double, price: String)

I would like to know why this works.