org.scalatest.EitherValues.scala Maven / Gradle / Ivy
Show all versions of scalatest_2.9.0-1 Show documentation
/*
* Copyright 2001-2011 Artima, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.scalatest
import org.scalatest.exceptions.StackDepthExceptionHelper.getStackDepthFun
/**
* Trait that provides an implicit conversion that adds left.value
and right.value
methods
* to Either
, which will return the selected value of the Either
if defined,
* or throw TestFailedException
if not.
*
*
* This construct allows you to express in one statement that an Either
should be left or right
* and that its value should meet some expectation. Here's are some examples:
*
*
*
* either1.right.value should be > 9
* either2.left.value should be ("Muchas problemas")
*
*
*
* Or, using assertions instead of matcher expressions:
*
*
*
* assert(either1.right.value > 9)
* assert(either2.left.value === "Muchas problemas")
*
*
*
* Were you to simply invoke right.get
or left.get
on the Either
,
* if the Either
wasn't defined as expected (e.g., it was a Left
when you expected a Right
), it
* would throw a NoSuchElementException
:
*
*
*
* val either: Either[String, Int] = Left("Muchas problemas")
*
* either.right.get should be > 9 // either.right.get throws NoSuchElementException
*
*
*
* The NoSuchElementException
would cause the test to fail, but without providing a stack depth pointing
* to the failing line of test code. This stack depth, provided by TestFailedException
(and a
* few other ScalaTest exceptions), makes it quicker for
* users to navigate to the cause of the failure. Without EitherValues
, to get
* a stack depth exception you would need to make two statements, like this:
*
*
*
* val either: Either[String, Int] = Left("Muchas problemas")
*
* either should be ('right) // throws TestFailedException
* either.right.get should be > 9
*
*
*
* The EitherValues
trait allows you to state that more concisely:
*
*
*
* val either: Either[String, Int] = Left("Muchas problemas")
*
* either.right.value should be > 9 // either.right.value throws TestFailedException
*
*/
trait EitherValues {
/**
* Implicit conversion that adds a value
method to LeftProjection
.
*
* @param either the LeftProjection
on which to add the value
method
*/
implicit def convertLeftProjectionToValuable[L, R](leftProj: Either.LeftProjection[L, R]) = new LeftValuable(leftProj)
/**
* Implicit conversion that adds a value
method to RightProjection
.
*
* @param either the RightProjection
on which to add the value
method
*/
implicit def convertRightProjectionToValuable[L, R](rightProj: Either.RightProjection[L, R]) = new RightValuable(rightProj)
/**
* Wrapper class that adds a value
method to LeftProjection
, allowing
* you to make statements like:
*
*
* either.left.value should be > 9
*
*
* @param leftProj A LeftProjection
to convert to LeftValuable
, which provides the
* value
method.
*/
class LeftValuable[L, R](leftProj: Either.LeftProjection[L, R]) {
/**
* Returns the Left
value contained in the wrapped LeftProjection
, if defined as a Left
, else throws TestFailedException
with
* a detail message indicating the Either
was defined as a Right
, not a Left
.
*/
def value: L = {
try {
leftProj.get
}
catch {
case cause: NoSuchElementException =>
throw new TestFailedException(sde => Some(Resources("eitherLeftValueNotDefined")), Some(cause), getStackDepthFun("EitherValues.scala", "value"))
}
}
}
/**
* Wrapper class that adds a value
method to RightProjection
, allowing
* you to make statements like:
*
*
* either.right.value should be > 9
*
*
* @param rightProj A RightProjection
to convert to RightValuable
, which provides the
* value
method.
*/
class RightValuable[L, R](rightProj: Either.RightProjection[L, R]) {
/**
* Returns the Right
value contained in the wrapped RightProjection
, if defined as a Right
, else throws TestFailedException
with
* a detail message indicating the Either
was defined as a Right
, not a Left
.
*/
def value: R = {
try {
rightProj.get
}
catch {
case cause: NoSuchElementException =>
throw new TestFailedException(sde => Some(Resources("eitherRightValueNotDefined")), Some(cause), getStackDepthFun("EitherValues.scala", "value"))
}
}
}
}
/**
* Companion object that facilitates the importing of ValueEither
members as
* an alternative to mixing it in. One use case is to import EitherValues
's members so you can use
* left.value
and right.value
on Either
in the Scala interpreter:
*
*
* $ scala -cp scalatest-1.7.jar
* Welcome to Scala version 2.9.1.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_29).
* Type in expressions to have them evaluated.
* Type :help for more information.
*
* scala> import org.scalatest._
* import org.scalatest._
*
* scala> import matchers.ShouldMatchers._
* import matchers.ShouldMatchers._
*
* scala> import EitherValues._
* import EitherValues._
*
* scala> val e: Either[String, Int] = Left("Muchas problemas")
* e: Either[String,Int] = Left(Muchas problemas)
*
* scala> e.left.value should be ("Muchas problemas")
*
* scala> e.right.value should be < 9
* org.scalatest.TestFailedException: The Either on which rightValue was invoked was not defined.
* at org.scalatest.EitherValues$RightValuable.value(EitherValues.scala:148)
* at .<init>(<console>:18)
* ...
*
*/
object EitherValues extends EitherValues