1
votes

When working through testing with FeatureSpec and using scenario, I have part of my code that sends a "failure" case class (i.e. ApplesNotAllowed) and is used via a scalaz disjunction.

Quick example:

val result = if (order.value != 10) {
    -\/(ApplesNotSupported(orderNumber))
  } else {
    \/-Option.empty[Orange]
  }

In my test suite, I can easily test for the case where I receive an Option.empty[Orange] by expecting that it shouldBe None. However, I do run into a problem when I want to test for the ApplesNotSupported case class being returned. How would I expect this "failure" that will acknowledge the test as passing since we want the "failure" to happen? Whenever I try to run my scenario, I get the error:

Validation is not success ApplesNotSupported(orderNumber)

Tried using interrupt does not solve the issue since it is not an exception, nor do we want to deliberately fail the test. Could it be an issue with using scalaz and ScalaTest?

I am fairly new to functional programming and programming in Scala overall, so any resources or suggestions help as I do have trouble searching for documentation.

3

3 Answers

4
votes

You may want to look in to using disjunction matchers when testing disjunctions: https://github.com/typelevel/scalaz-scalatest/blob/master/src/main/scala/DisjunctionMatchers.scala

This is the best way to test based on the result of a disjunction. You can match based on the disjunction itself:

must be_\/-
must be_-\/

Or go a step further and match on the result of the disjunction and the value it contains:

must be_\/-(value)
must be_-\/(value)

I don't personally use ScalaTest, but it looks like it should be the same as it is in specs2.

1
votes

What about wrapping it in Try and do something like this:

import org.scalatest.{FunSuite, Matchers}
import org.specs2.mock.Mockito

import scala.util.{Failure, Success, Try}

/**
  * Created by ssharma on 4/18/17.
  */
class UnitTest extends FunSuite with Matchers{
     class A {

       def t1(x: Int): Try[Int] = Try(t(x))

       private def t(x: Int): Int = {
         x match {
           case 1 => 1
           case _ => throw new RuntimeException
         }
       }
     }

  test("A") {
    val b = new A
    assert(b.t1(1)isSuccess)
  }

  test("A fail") {
    val b = new A
    assert(b.t1(2)isFailure)
  }
}
0
votes

I am not familiar with either scalaz or disjunctions but it sounds like the intercept functionality in scalatest's assertions (http://www.scalatest.org/user_guide/using_assertions) may help.

You define the type of exception you are expecting with intercept and you run the code that will throw the exception within the function. You can assign the result of intercept to a val which then you can compare to the expected value using assert or assertResult from scalatest.

Hope this can help! :)