org.specs.mock.Mocker.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of specs_2.8.0.Beta1-RC8
Show all versions of specs_2.8.0.Beta1-RC8
specs is a Behaviour-Driven-Design
framework
The newest version!
/**
* Copyright (c) 2007-2009 Eric Torreborre
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of
* the Software. Neither the name of specs nor the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written permission.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package org.specs.mock
import org.specs.matcher._
import java.util.regex.Pattern
import org.specs.specification._
/**
* This trait allows to define mocked method and to specify how they can be called
* It is used in 3 steps:
* - first create a mock object which will override the methods that you want to mock
*
val mock = new MyClass {
* override def method { record }
* }
* - implement the mocked methods with the
Mocker.record
method
* - declare expectations in your specification:
expect { mock.method }
* - every expectation will be automatically checked at the end of the example (see the implementation of the
*
ExampleLifeCycle
trait)
*/
trait Mocker extends ProtocolTypes with LifeCycle with MockMatchers with ExpectationsListener {
/** protocol storing mocks expectations */
val protocol = new Protocol
/**
* this variable is used to distinguish uses of the record
method. Either during
* expectation definitions or during actual calls
*/
private var expectingMode = 0
/**
* expects some methods to be called on mocks. Any call to the record
method
* during the evaluation of v will create a new expectation
* Usage: expect(twoOf, exclusively) { mock.method }
*/
def expect(t: ProtocolType, e: Exclusivity)(v: => Any): Protocol = {
if (expectingMode == 0) protocol.clear
expectingMode += 1
if (e == exclusively)
protocol.exclusive = true
protocol.expect(t)(v).isExpectation
expectingMode -= 1
protocol
}
/**
* default expect method: inAnyOrder, nonExclusively
*/
def expect(v: => Any): Protocol = expect(inAnyOrder, nonExclusively)(v)
/**
* next default expect method: any protocol type "t", nonExclusively
*/
def expect(t: ProtocolType)(v: => Any): Protocol = expect(t, nonExclusively)(v)
/**
* records a method call.
If the expecting mode is > 0, that is, if we are inside an expect { } block
* then add an expectation with the mocked method name. Otherwise, this is a regular call which is recorded as
* a received call
*/
def record: Unit = {
if (expectingMode > 0)
protocol.expectCall(methodName)
else
protocol.receiveCall(methodName)
}
/**
* records a method call and return a specific value.
* Usage: val mock = new MyClass { override def method: Int = recordAndReturn(1) }
* @return 1 on every call to the method method
*/
def recordAndReturn[T](v: T): T = {
record
v
}
/**
* convenience method to add an expectation to check method parameters during calls
* Usage: def createMock(f: Movie => Unit) = new MovieRater {
* override def register(m: Movie) = record(f(m))
* }
* then val mock = createMock((m: Movie) => {m.name must notBe(null)})
*/
def record[T](v: T): T = {
record
v
}
/**
* gets the name of the recorded method by throwing an exception and parsing the stacktrace
*/
private def methodName = {
val message = (new Exception()).getStackTrace.toList.dropWhile(!_.toString.contains("record")).dropWhile(_.toString.contains("record"))(0).toString
val matcherExp = Pattern.compile(".*\\.(.*\\(.*)").matcher(message)
matcherExp.find
matcherExp.group(1)
}
/**
* clears the protocol before each example to start with new expectations
*/
override def beforeExample(ex: Examples) = {
super.beforeExample(ex)
protocol.clear
}
/**
* clears the protocol after each example to start with new expectations
*/
override def afterExample(ex: Examples) = {
protocol.clear
super.afterExample(ex)
}
/**
* checks expectations if some have been made during the test
*/
override def afterExpectations(ex: Examples) = {
if (protocol.isSpecified) {
ex.addExpectation
(new Expectation(protocol)) must beMet
}
super.afterExpectations(ex)
}
/**
* syntactic sugar allowing to write
* expect {
* twoOf { // instead of expect(twoOf) {
* mock.call
* }
* }
*/
implicit def protocolTypeToProtocolDef(t: ProtocolType)(v: => Any) = {
expect(t, nonExclusively)(v)
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy