package org.specs.mock
import org.jmock.lib.legacy.ClassImposteriser
import org.jmock.lib.action._
import org.jmock.api._
import org.jmock.internal.State
import org.jmock.internal.StatePredicate
import java.util.Collection
import java.util.Iterator
import org.hamcrest._
import org.hamcrest.core._
import org.hamcrest.core.AnyOf._
import org.jmock._
import org.specs.specification._
import org.specs.util.Property
import org.specs.ExtendedThrowable._
import org.jmock.internal.matcher.MethodNameMatcher
import org.specs.collection.JavaCollectionsConversion._

/** 
 * This object can be used to import and rename some functions in case of a conflict with some other trait.
 * For example the trait Suite in ScalaTest uses an expect method too
 */
object JMocker extends JMocker {
  def addAssertion = null
}

/** 
 * The JMocker trait is used to give access to the mocking functionalities of the JMock library 
 */
trait JMocker extends JMockerExampleLifeCycle with HamcrestMatchers with JMockActions with AssertionListener { outer =>

  /**
   * the mock method is used to create a mock object
   * Usage:<pre>val mocked = mock(classOf[InterfaceToMock])</pre><br/>
   * Classes can be mocked too, but the ClassImposterizer trait has to be added to the extensions
   * @returns the mocked object
   */
  def mock[T](c: java.lang.Class[T]): T =  context.mock(c).asInstanceOf[T]

  /** 
   * mocks a class and give the resulting mock a name. jMock expects mocks of the same class to have different names
   * @returns the mocked object
   */
  def mock[T](c: java.lang.Class[T], name: String) =  context.mock(c, name).asInstanceOf[T]

  /** 
   * mocks a class and add expectations. Usage <code>willReturn(as(classOf[MyInterface]){m: MyInterface => one(m).method })<code>
   * @returns the mocked object and the evaluation of the block of expectations
   */
  def as[T](c: java.lang.Class[T])(expects: Function1[T, Any]) = {
    val mocked = context.mock(c).asInstanceOf[T]
    (mocked, expects) 
  }

  /** 
   * mocks a class and add expectations, specifying the mock with a name
   * @returns the mocked object and the evaluation of the block of expectations
   */
  def as[T](c: java.lang.Class[T], name: String)(expects: Function1[T, Any]) = {
    val mocked = context.mock(c, name).asInstanceOf[T]
    (mocked, expects) 
  }

  /** 
   * mocks a class several times and add expectations for each mock. Usage <code>willReturn(as(classOf[MyInterface])
   *   {m1: MyInterface => one(m1).method },
   *   {m2: MyInterface => one(m2).method },
   * )<code>
   * However, it is shorter to use <code>willReturnIterable:
   * one(workspace).projects willReturnIterable(classOf[Project], 
           {p: Project => one(p).name willReturn "p1" },
           {p: Project => one(p).name willReturn "p2" })<code>
   * @returns the mocked object and the evaluation of the block of expectations
   */
  def as[T](c: java.lang.Class[T], expects: Function1[T, Any]*) = {
    expects.toList.zipWithIndex map { x =>
      val (block, i) = x
      (context.mock(c, c.getName + "_" + i).asInstanceOf[T], block)
    }
  }

  /** 
   * the code block being evaluated should contain some expectations being added to the expectations variable
   * Then the expectations are "freezed" by calling the checking method on context and the actual system behaviour can
   * be exercised
   */
  def expect(block: => Any) = {
    val result = block;
    context.checking(expectations);
    result
  }
  
  /** 
   * Adds an isAssertion method to any mock expectation to better count the number of assertions
   */
  implicit def anyToAssertionCounter(a: =>Any) = new AssertionCounter(a)
  /** 
   * Adds an isAssertion method to any mock expectation to better count the number of assertions
   */
  class AssertionCounter(a: =>Any) {
    /** adds an assertion to the AssertionListener trait */
    def isAssertion = { addAssertion; a }
  }

  /** 
   * Adds call constraint method to integers to express the exactly, atLeast, atMost
   */
  implicit def intToCallConstraint(i: Int) = new IntCallConstraint(i)
  class IntCallConstraint(i: Int) {
    def of[T](a: T) = exactly(i).of(a)
    def atLeastOf[T](a: T) = atLeast(i).of(a)
    def atMostOf[T](a: T) = atMost(i).of(a)
  }

  /** 
   * Adds call constraint method to a range, to express the between constraint
   */
  implicit def RangeToCallConstraint(r: Range) = new RangeCallConstraint(r)
  class RangeCallConstraint(r: Range) {
    def of[T](a: T) = between(r.start, r.end).of(a)
  }
  
  /** expecting exactly one call to the mock */
  def one[T](m: T) = expectations.one(m)

  /** expecting exactly count calls to the mock */
  def exactly(count: Int) = expectations.exactly(count)
    
  /** expecting atLeast count calls to the mock */
  def atLeast(count: Int) = expectations.atLeast(count)
    
  /** expecting between minCount and maxCount (inclusive) calls to the mock */
  def between(minCount: Int, maxCount: Int) = expectations.between(minCount, maxCount)

  /** expecting at Most calls to the mock */
  def atMost(count: Int) = expectations.atMost(count)
    
  /** allowing any calls to mocks */
  def allowing[T](mockObjectMatcher: Matcher[T]) = expectations.allowing(mockObjectMatcher)
    
  /** allowing any calls to a mock with method names like the passed parameter, returning default values */
  def allowingMatch[T](mock: T, methodName: String) = expectations.allowing(new IsSame(mock)).method(withName(methodName))

  /** allowing any calls to any mock with method names like the passed parameter, returning default values */
  def allowingMatch(methodName: String) = expectations.allowing(anything).method(withName(methodName))

  /** allowing any calls to the mock */
  def allowing[T](mockObject: T) = expectations.allowing(mockObject)
    
  /** ignoring any calls to the mock, returning default values */
  def ignoring[T](mockObject: T) = expectations.ignoring(mockObject)
    
  /** ignoring any calls to the mock, returning default values */
  def ignoring[T](mockObjectMatcher: Matcher[T]) = expectations.ignoring(mockObjectMatcher)
    
  /** ignoring any calls to the mock with method names like the passed parameter, returning default values */
  def ignoringMatch(methodName: String) = expectations.ignoring(anything).method(withName(methodName))

  /** ignoring any calls to a mock with method names like the passed parameter, returning default values */
  def ignoringMatch[T](mock: T, methodName: String) = expectations.ignoring(new IsSame(mock)).method(withName(methodName))
 
  /** forbidding any calls to the mock */
  def never[T](mockObject: T) = expectations.never(mockObject)

  /** constraining the latest call expectation with a Hamcrest matcher */
  def `with`[T](matcher: Matcher[T]) = expectations.`with`(matcher)

  /** shortcut for expectations.`with`(new IsAnything[Int]) */
  def anyInt = any(classOf[Int])

  /** shortcut for expectations.`with`(new IsAnything[Long]) */
  def anyLong = any(classOf[java.lang.Long])

  /** shortcut for expectations.`with`(new IsAnything[Short]) */
  def anyShort = any(classOf[Short])

  /** shortcut for expectations.`with`(new IsAnything[Boolean]) */
  def anyBoolean = any(classOf[Boolean])

  /** shortcut for expectations.`with`(new IsAnything[Float]) */
  def anyFloat = any(classOf[Float])

  /** shortcut for expectations.`with`(new IsAnything[Double]) */
  def anyDouble = any(classOf[Double])

  /** shortcut for expectations.`with`(new IsAnything[Char]) */
  def anyChar = any(classOf[Char])

  /** shortcut for expectations.`with`(new IsAnything[Byte]) */
  def anyByte = any(classOf[Byte])

  /** shortcut for expectations.`with`(new IsAnything[String]) */
  def anyString = any(classOf[String]) 

  /** shortcut for expectations.`with`(new IsAnything[T]) */
  def any[T](t: java.lang.Class[T]) = expectations.`with`(anything[T])

  /** shortcut for expectations.`with`(new IsInstanceOf[T]) */
  def a[T](t: java.lang.Class[T]) = {expectations.`with`(new IsInstanceOf(t)); null.asInstanceOf[T]}

  /** shortcut for expectations.`with`(new IsInstanceOf[T]) */
  def an[T](t: java.lang.Class[T]) = a(t)

  private def trueMatcher[T] = new org.hamcrest.TypeSafeMatcher[T]() {
    def matchesSafely(a: T) = true
    def describeTo(d: org.hamcrest.Description) = {}
  }
  /** always match the parameter */
  def a[T] = `with`(trueMatcher[T])

  /** always match the parameter */
  def an[T] = `with`(trueMatcher[T])

  
  /** shortcut for expectations.`with`(new IsNull[T]) */
  def aNull[T](t: java.lang.Class[T]) = {expectations.`with`(new IsNull[T]); null.asInstanceOf[T]}

  /** shortcut for expectations.`with`(new IsNot(IsNull[T])) */
  def aNonNull[T](t: java.lang.Class[T]) = {expectations.`with`(new IsNot(new IsNull[T])); null.asInstanceOf[T]}

  /** shortcut for expectations.`with`(new IsEqual[T](value)) */
  def equal[T](value: T)  = { expectations.`with`(new IsEqual[T](value)); value }

  /** shortcut for expectations.`with`(new IsSame[T](value)) */
  def same[T](value: T)  = {expectations.`with`(new IsSame[T](value)); value}
  
  /** Adapter class to use specs matchers as Hamcrest matchers */
  case class HamcrestMatcherAdapter[T](m: org.specs.matcher.Matcher[T]) extends org.hamcrest.TypeSafeMatcher[T] {
     var resultMessage: String = ""
     def matchesSafely(item: T) = {
       val result = m.apply(item)
       if (result._1)
         resultMessage = result._2
       else
         resultMessage = result._3
       result._1
     }
     def describeTo(description: Description ) = {
       new org.hamcrest.StringDescription(new StringBuffer(resultMessage))
     }
  }

  /** @returns a specs matcher adapted into Hamcrest matcher */
  implicit def will[T](m: org.specs.matcher.Matcher[T]): T = {
    expectations.`with`(new HamcrestMatcherAdapter[T](m))
    null.asInstanceOf[T]
  }
  
  /** this method is used to avoid the use of the reserved Scala keyword 'with'. This is also consistent with the way to specify returned values */
  def will[T](m: org.hamcrest.Matcher[T]): T = {
    expectations.`with`(m)
    null.asInstanceOf[T]
  }

  /** allow the return value of the method to be more precisely specified with a JMock action, like a returnValue action */
  implicit def toAction[T](v: T) = new JMockAction(v)

  /** 
   * This class allows a block of code to be followed by some actions like returning a value or throwing an exception
   * When we wish to return a mock and define expectations at the same time:
   * <code>willReturn(classOf[MyInterface]) { m1: MyInterface =>
   *    one(m1).method }
   * <code>
   * It is necessary to first create the mock, set it as a returned object through a ReturnValueAction
   * then to trigger the block containing the expectations for that mock
   */
  class JMockAction[T](v: T) {

    private[this] def wrap[T](collection: java.util.Collection[T]) = collection.toArray

    /** sets a value to be returned by the mock */
    def willReturnValue(result: T) = expectations.will(new ReturnValueAction(result))

    /** sets a value to be returned by the mock */
    def willReturn(result: T) = expectations.will(new ReturnValueAction(result))

    /** sets an action which will return a mock of type Class[T] and being specified by a function triggering expectations */
    def willReturn(c: java.lang.Class[T])(f: Function1[T, Any]): Unit = {
      val mocked = context.mock(c).asInstanceOf[T]
      expectations.will(new ReturnValueAction(mocked))
      f(mocked)
    }
    
    /** 
     * sets an action which will return a mock of type Class[T] and being specified by a function triggering expectations.
     * It is supposed to be used in conjunction with the <code>as</code> method which mocks an object and creates a function
     * defining the mock expectations
     */
    def willReturn(result: (T, Function1[T, Any])) = {
      expectations.will(new ReturnValueAction(result._1))
      result._2.apply(result._1)
    }

    def willReturnEach(values: T*) = {
      will(new ActionSequence((values map { x: T => returnValue(x) }).toArray))
    }

   /** 
    * will return a list of mocks from the same class several times and add expectations for each mock. 
    * Usage <code>willReturnIterable(as(classOf[MyInterface])
    *   {m1: MyInterface => one(m1).method },
    *   {m2: MyInterface => one(m2).method },
    * )<code>
    * However, it is shorter to use <code>willReturnIterable:
    * one(workspace).projects willReturnIterable(classOf[Project], 
            {p: Project => one(p).name willReturn "p1" },
            {p: Project => one(p).name willReturn "p2" })<code>
    */
    def willReturnIterable[S, T <: Iterable[S]](c: java.lang.Class[S], results: Function1[S, Any]*): Unit = {
      willReturn(results.toList.zipWithIndex map { x =>
        val (block, i) = x
        (context.mock(c, c.getName + "_" + i).asInstanceOf[S], block)
      })
    }
 
   /** 
    * will return a list of values of type S, and containing some associated blocks to set expectations for those values which may be mocks 
    * Usage <code>willReturnIterable(as(classOf[MyInterface]){m1: MyInterface => one(m1).method },
    *   as(classOf[MyInterface]){m2: MyInterface => one(m2).method })
    * <code>
    */
    def willReturnIterable[S, T <: Iterable[S]](results: (S, Function1[S, Any])*): Unit = willReturn(results.toList)

   /** 
    * will return a list of values of type S, and containing some associated blocks to set expectations for those values which may be mocks 
    * Usage <code>willReturnIterable(List(as(classOf[MyInterface]){m1: MyInterface => one(m1).method },
    *   as(classOf[MyInterface]){m2: MyInterface => one(m2).method }))
    * <code>
    */
    def willReturn[S, T <: Iterable[S]](results: List[(S, Function1[S, Any])]): Unit = {
      expectations.will(new ReturnValueAction(results.map(_._1).toList))
      results foreach { result =>
        result._2.apply(result._1)
      }
    }

    /** sets an exception to be thrown by the mock */
    def willThrow[X <: Throwable](t: X) = expectations.will(new ThrowAction(t))

    /** set up a JMock action to be executed */
    def will(action: Action) = expectations.will(action)
    
    def willReturn[T](stored: CapturingParam[T]) = will(stored.value)

  }
  /** factory method to create a new capturing parameter */
  def capturingParam[T] = new CapturingParam[T]

  /** 
   * Capturing Parameters allow to capture the value of a parameter passed to a mock method.<p/>
   * The most frequent usage for this is to be able to return the parameter as the return value of the method.<p/>
   * Usage:<pre>
   * val s = capturingParam[String]
   * classOf[ToMock].expects(one(_).method(s.capture) willReturn s)
   * </pre>
   * It is also possible to use the <code>map</code> function to return a value of a different type:<pre> 
   * willReturn s.map(_.size)
   * </pre>
   * And the capturing parameter can still be checked for its validity using <code>must(specs matcher)</code>:<pre>
   * classOf[ToMock].expects(one(_).method(s.must(beMatching("h.*")).capture) willReturn s)
   * </pre>
   */
  class CapturingParam[T] extends org.hamcrest.TypeSafeMatcher[T]() {
    /** stores the captured value, to be able to return it later */
    var captured: T = _

    /** by default the captured parameter is the first parameter of the mocked method */
    private var parameterIndex  = 0

    /** option mapping function to apply before returning the value */
    private var function: Option[T => _] = None

    /** optional matcher checking the captured value */
    private var matcher: Option[HamcrestMatcherAdapter[T]] = None

    /** the returned value as a ReturnValueAction object */
    def value = new ReturnValueAction[T]() {
      override def invoke(i: Invocation) = function match {
        case None => i.getParameter(parameterIndex)
        case Some(f) => f(i.getParameter(parameterIndex).asInstanceOf[T])
      }
    }

    /** this method stores the parameter value and apply the optional matcher */
    def matchesSafely(a: T): Boolean = { 
      captured = a
      matcher match {
        case None => true
        case Some(m) => m.matchesSafely(a) 
      } 
    }

    /** this describes the result of the optional matchers */
    def describeTo(desc: Description) = matcher.map(_.describeTo(desc))

    /** capture will add this as a new Matcher to expect */
    def capture = `with`(this)

    /** capture will add this as a new Matcher to expect, with the user-specified index of the parameter */
    def capture(i: Int) = { parameterIndex = i; `with`(this) }

    /** adds a function to use when returning the captured value */
    def map[S](f: T => S) = { function = Some(f); this }

    /** adds a matcher to use when checking the parameter */
    def must(m: org.specs.matcher.Matcher[T]) = { matcher = Some(HamcrestMatcherAdapter(m)); this }
  }


  /** set up a jMock action to be executed */
  def will(action: Action) = expectations.will(action)
    
  /** @returns a state with name <code>name<code>, creating a new one if necessary */
  def state(name: String) = context.states(name)

  /** specifies that a call can only occur following the specific condition on a state */
  def when(predicate: StatePredicate) = expectations.when(predicate)
    
  /** specifies that after a call, a State object will be in a specific state */
  def then(state: State) = expectations.then(state)

  /** allows any block of expectations to be followed by state actions and expectations */
  implicit def afterCall(v: Any) = new StateConstraint(v)

  /** this class allows any block of expectations to be followed by state actions and expectations */
  class StateConstraint(expectation: Any) {
    def set(state: State) = expectations.then(state)
    def when(predicate: StatePredicate) = expectations.when(predicate)
  }

  /** adds a constraint to the expectations to declare that an expected call must happen in sequence */
  def inSequence(sequence: Sequence) = expectations.inSequence(sequence)

  /** this class allows an expectation to declare that another expectation should follow */
  implicit def after(v: =>Any) = new InSequenceThen(v)

  /** this class allows an expectation to declare that another expectation should follow */
  class InSequenceThen(firstExpectation: =>Any) {
    val sequence = {
      val s = context.sequence("s")
      firstExpectation; inSequence(s)
      s
    }  
    def then(otherExpectation: Any) = {
      otherExpectation
      inSequence(sequence)
      this
    }
  }
  /** 
   * One liner function for expectations.<p>
   * Usage:<code>  
   *   expect(classOf[List[Int]]) { one(_).size } { l =>
   *     l.size
   *   }
   *</code>
   */
  def expect[T](c: Class[T])(f: T => Any): ExpectBlock[T] = ExpectBlock(mock(c), f)
  case class ExpectBlock[T](mocked: T, f: T => Any) {
    
    def in(f2: T => Any) = isExpecting(mocked)(f)(f2)
    def mock: T = { expect { f(mocked) }; mocked }
  }
  private def isExpecting[T](m: =>T)(f: T => Any)(f2: T => Any): Any = {
    val lastExample: Example = addAssertion
    var result: Any = null
    expect { f(m) }
    lastExample.in { result = f2(m) }.failures
    result
  }
  /** 
   * Extends Class objects with the one-liner <code>expects</code>
   * Usage:<code>  
   *   classOf[List[Int]].expect { one(_).size } { l =>
   *     l.size
   *   }
   *</code>
   */
  implicit def classToMock[T](c: Class[T]) = ClassToMock(c)
  /** 
   * Extends Class objects with the one-liner <code>expects</code>
   * Usage:<code>  
   *   classOf[List[Int]].expect { one(_).size } { l =>
   *     l.size
   *   }
   *</code>
   */
  case class ClassToMock[T](c: Class[T]) {
    private def block(f: T => Any) = ExpectBlock(mock(c), f)
    def expects(f: T => Any) = block(f)
    def expectsOne(f: T => Any) = block((m:T) => f(one(m)))
    def expectsSome(f: T => Any) = block((m:T) => f(atLeast(0).of(m)))
    def expectsAtLeastOne(f: T => Any) = block((m:T) => f(atLeast(1).of(m)))
    def expectsAtLeast(i: Int)(f: T => Any) = block((m:T) => f(atLeast(i).of(m)))
    def expectsAtMost(i: Int)(f: T => Any) = block((m:T) => f(atMost(i).of(m)))
    def expectsExactly(i: Int)(f: T => Any) = block((m:T) => f(exactly(i).of(m)))
    def expectsBetween(min: Int, max: Int)(f: T => Any): ExpectBlock[T] = block((m:T) => f(between(min, max).of(m)))
    def expectsBetween(range: Range)(f: T => Any): ExpectBlock[T] = expectsBetween(range.start, range.end)(f)
    def allows[S](mockObjectMatcher: Matcher[S]): ExpectBlock[T] = block((m:T) => outer.allowing(mockObjectMatcher))
    /** allowing any calls to a mock with method names like the passed parameter, returning default values */
    def allowsMatch(methodName: String) = block((m:T) => outer.allowingMatch(m, methodName))
    /** allowing any calls to the mock */
    def isAllowed = block((m:T) => outer.allowing(m))
    /** ignoring any calls to the mock, returning default values */
    def isIgnored =  block((m:T) => outer.ignoring(m))
    /** ignoring any calls to the mock, returning default values */
    def ignores[S](mockObjectMatcher: Matcher[S]) = block((m:T) => outer.ignoring(mockObjectMatcher))
    /** ignoring any calls to the mock with method names like the passed parameter, returning default values */
    def ignoresMatch(methodName: String) = block((m:T) => outer.ignoringMatch(m, methodName))
    /** forbidding any calls to the mock */
    def neverExpects(f: T => Any) = block((m:T) => f(outer.never(m)))

  }
}

/**
 * This trait provide methods to build Hamcrest matchers. It actually contains only 2 methods since all Hamcrest matchers can
 * be created by static methods in the Hamcrest library classes
 */
trait HamcrestMatchers {
  /** shortcut for new IsAnything[T] */
  def anything[T] = new IsAnything[T]

  /** @returns a MethodNameMatcher to use in conjunction with allowing(mock) */
  def withName(nameRegex: String) = new MethodNameMatcher(nameRegex)
}

/**
 * This trait provide methods to build jMock actions
 */
trait JMockActions {
  /** action returning a value */
  def returnValue[T](result: T) = new ReturnValueAction(result)

  /** action throwing an exception of type T*/
  def throwEx[T <: Throwable](t: T) = new ThrowAction(t)
    
  /** action executing several other actions */
  def doAll(actions: Action*) = new DoAllAction(actions.toArray)
    
  /** @returns a sequence of actions where the first action is executed after the first call, the second action
   * after the second call, and so on */
  def onConsecutiveCalls(actions: Action*) = new ActionSequence(actions.toArray)
}

/** 
 * This trait defines when a jMock context will be created and expectations checked.
 * The context and expectations are always created at the beginning of an Example, then checked just after the test has been executed. Executing a test can also trigger an ExpectationError (from the jMock library). This error will be transformed into a FailureException
 */
trait JMockerExampleLifeCycle extends ExampleLifeCycle with JMockerContext {

  /** 
   * before any example, a new context and new expectations should be created
   */
  override def beforeExample(ex: Example) = {
    super.beforeExample(ex)
    restart
  }

  /** 
   * An expectation error may be thrown during the execution of a test
   * In that case, it is transformed to a failure exception
   */
  override def executeTest(ex: Example, t: => Any) = {
    try { super.executeTest(ex, t) } catch { case e: ExpectationError => throw createFailure(e) }
  }

  /** 
   * After a test the context is verified. If some more expectations are not met an ExpectationError is thrown
   * In that case, it is transformed to a failure exception
   */
  override def afterTest(ex: Example) = {
    try {
      context.assertIsSatisfied
    } catch {
      case e: ExpectationError => {restart; throw createFailure(e)}
    }
    restart
    super.afterTest(ex)
  }
  
  private[this] def createFailure(e: ExpectationError) = FailureException(e.toString)
}

/** 
 * This trait contains the jMock Mockery object and current expectations
 */
trait JMockerContext extends Imposterizer {
  /** the context holds the mocks, the expectations so is able to get the calls and check them */
  var context = createMockery

  /** call expectations with optional constraints on the number of calls, on parameters, return values,... */
  var expectations = new Expectations()
  
  /** creates a new context and a new Expectations object */
  def restart = { context = createMockery; expectations = new Expectations() }

  /** 
   * This method can be used to check the context. It will always restart the context, even if there is an ExpectationError
   * In that case, it is transformed to a failure exception
   */
  def checkContext = {
    try {
      context.assertIsSatisfied
    } catch {
      case e: ExpectationError => {restart; throw e}
    }
    restart
  }
}


/** 
 * This trait allows to mock classes instead of interfaces only. This will require the cglib and objenesis libraries on the path. 
 */
trait ClassMocker extends Imposterizer {
  override def newMockery = new Mockery() { setImposteriser(ClassImposteriser.INSTANCE) }
}

/** 
 * Naming scheme adding a number to each anonymous mock 
 */
class CountingNamingScheme extends org.jmock.api.MockObjectNamingScheme {
  private val camelCaseNamingScheme = new org.jmock.lib.CamelCaseNamingScheme
  private var counter = 1
  def defaultNameFor(typeToMock: Class[_]) = { 
    var name = camelCaseNamingScheme.defaultNameFor(typeToMock)
    if (counter > 1) {
      name = (name + " " + counter)
    }
    counter += 1; 
    name
  }
}
/** 
 * Abstract trait for creating a mocking context. By default, only allows to mock interfaces 
 */
trait Imposterizer {
  def createMockery = { val mockery = newMockery; mockery.setNamingScheme(new CountingNamingScheme); mockery }
  def newMockery = new Mockery
}