Skip to content
Browse files

Add license text and documentation

  • Loading branch information...
1 parent 9b655b4 commit 53d5f4addffe4c65eae6ad6574d2f2185889ff82 @paulbutcher committed Feb 25, 2011
Showing with 268 additions and 0 deletions.
  1. +19 −0 LICENSE
  2. +67 −0 README.md
  3. +182 −0 src/main/scala/package.scala
View
19 LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2011 Paul Butcher
+
+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.
+
+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.
View
67 README.md
@@ -0,0 +1,67 @@
+# Borachio
+
+Native Scala mocking.
+
+## Examples
+
+### Mocking objects
+
+ def testTurtle {
+ val t = mock[Turtle]
+
+ t expects 'penDown
+ t expects 'turn withArgs (90.0)
+ t expects 'forward withArgs (10.0)
+ t expects 'getPosition returning (0.0, 10.0)
+
+ drawLine(t)
+ }
+
+### Mocking functions
+
+ def testFoldLeft() {
+ val f = mockFunction[String, Int, String]
+
+ f expects ("initial", 0) returning "intermediate one"
+ f expects ("intermediate one", 1) returning "intermediate two"
+ f expects ("intermediate two", 2) returning "intermediate three"
+ f expects ("intermediate three", 3) returning "final"
+
+ expect("final") { Seq(0, 1, 2, 3).foldLeft("initial")(f) }
+ }
+
+For more examples, see `src/test/scala/examples`.
+
+## Building
+
+Build with [sbt](http://code.google.com/p/simple-build-tool/):
+
+ sbt update
+ sbt test
+
+## Design Principles
+
+Existing Java mocking libraries work with Scala but:
+
+* They don't handle things that Java doesn't support, such as curried functions, higher-order functions, etc.
+* None of the Java mocking libraries support Android (because the Dalvik VM doesn't support runtime code generation). Borachio does not depend on [cglib](http://cglib.sourceforge.net/), meaning that it runs just fine on Android.
+
+## To do
+
+* Argument matchers
+* Better handling of overloaded methods
+* Better handling of primitive types (when returning them from a proxy mock)
+
+## License
+
+[MIT License](http://www.opensource.org/licenses/mit-license.php). See LICENSE.
+
+## Name
+
+Borachio is a character from _Much Ado About Nothing_, the plot of which revolves around identity and impersonation. Thanks to [J. Nathan Matias](http://www.natematias.com/) for the suggestion.
+
+## Thanks
+
+The inner workings of Borachio's proxy mocks were inspired by [`scala.tools.reflect.Mock`](http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk/src/compiler/scala/tools/reflect/Mock.scala) written by Paul Philips in the Scala compiler.
+
+Thanks also to Bill Venners for discussion and suggestions.
View
182 src/main/scala/package.scala
@@ -0,0 +1,182 @@
+// Copyright (c) 2011 Paul Butcher
+//
+// 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.
+//
+// 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 com
+
+/**
+ * =Borachio: Native Scala mocking=
+ *
+ * Borachio integrates with [[http://www.scalatest.org/ ScalaTest]] and adds native mocking support.
+ * To use it, mix the [[com.borachio.MockFactory]] trait into a ScalaTest Suite:
+ *
+ * {{{
+ * class MyTest extends Suite with MockFactory
+ * }}}
+ *
+ * Borachio supports two different mocking styles - ''Functional mocking'' and ''Proxy mocking''.
+ *
+ * ==Functional mocking==
+ *
+ * Functional mocks are created with `mockFunction`. The following, for example, creates a mock
+ * function taking a single `Int` argument and returning a `String`:
+ *
+ * {{{
+ * val m = mockFunction[Int, String]
+ * }}}
+ *
+ * Expectations then can be set on a mock function. The following, for example, says that we expect our
+ * mock to be called once with the argument `42`, and that when called like that it should return the
+ * value `"Forty two"`:
+ *
+ * {{{
+ * m expects (42) returning "Forty two" once
+ * }}}
+ *
+ * ==Proxy mocking==
+ *
+ * Proxy mocks are created with `mock`. The following, for example, creates a mock which implements
+ * all the traits (interfaces) implemented by the `Turtle` class:
+ *
+ * {{{
+ * val m = mock[Turtle]
+ * }}}
+ *
+ * Expectations can then be set on each of the methods within those traits. For example:
+ *
+ * {{{
+ * m expects 'setPosition withArgs (10.0, 10.0)
+ * m expects 'forward withArgs (5.0)
+ * m expects 'getPosition returning (15.0, 10.0)
+ * }}}
+ *
+ * ==Expectations==
+ *
+ * Expectations can be set on the arguments a function or method is called with and how many times
+ * it should be called. In addition, mocks can be instructed to return a particular value or throw
+ * an exception when that expectation is met.
+ *
+ * ===Arguments===
+ *
+ * At the moment, Borachio only supports simple argument equality matching. An expectation is met
+ * if the actual arguments equal the expected arguments. In the future more sophisticated matching
+ * will be suported.
+ *
+ * To specify expected arguments for a functional mock, use `expects`. To specify expected
+ * arguments for a proxy mock, use `withArgs` or `withArguments`.
+ *
+ * If no expected arguments are given, mocks accept any arguments.
+ *
+ * ===Return value===
+ *
+ * Mocks can be instructed to return a specific value with `returns` or `returning`:
+ *
+ * {{{
+ * m1 returns 42
+ * m2 expects ("this", "that") returning "the other"
+ * }}}
+ *
+ * If no return value is specified, functional mocks return `null.asInstanceOf[R]` where `R` is the
+ * return type (which equates to `0` for `Int`, `0.0` for `Double` etc.).
+ *
+ * If no return value is specified, proxy mocks return `null`. This works correctly for most return
+ * types, but not for methods returning primitive types (`Int`, `Double` etc.), where returning
+ * `null` leads to a `NullPointerException`. So you will need to explicitly specify a return value
+ * for such methods. This restriction may be lifted in the future.
+ *
+ * ===Exceptions===
+ *
+ * Instead of a return value, a mock can be instructed to throw:
+ * {{{
+ * m expects ("this", "that") throws new RuntimeException("what's that?")
+ * }}}
+ *
+ * ===Call count===
+ *
+ * By default, mocks expect one or more calls (i.e. only fail if the function or method is never
+ * called). An exact number of calls or a range can be set with `repeat`:
+ *
+ * {{{
+ * m1 returns 42 repeat 3 to 7
+ * m2 expects (3) repeat 10
+ * }}}
+ *
+ * There are various aliases for common expectations and styles:
+ *
+ * {{{
+ * m1 expects ("this", "that") once
+ * m2 returns "foo" noMoreThanTwice
+ * m3 expects (42) repeated 3 times
+ * }}}
+ *
+ * For a full list, see [[com.borachio.Expectation]].
+ *
+ * ==Ordering==
+ *
+ * By default, expectations can be satisfied in any order. For example:
+ *
+ * {{{
+ * m expects (1)
+ * m expects (2)
+ * m(2)
+ * m(1)
+ * }}}
+ *
+ * A specific sequence can be enforced with `inSequence`:
+ *
+ * {{{
+ * inSequence {
+ * m expects (1)
+ * m expects (2)
+ * }
+ * m(2) // throws ExpectationException
+ * m(1)
+ * }}}
+ *
+ * Multiple sequences can be specified. As long as the calls within each sequence happen in the
+ * correct order, calls within different sequences can be interleaved. For example:
+ *
+ * {{{
+ * val m1 = mock[Turtle]
+ * val m2 = mock[Turtle]
+ *
+ * inSequence {
+ * m1 expects 'setPosition withArguments (0.0, 0.0)
+ * m1 expects 'penDown
+ * m1 expects 'forward withArguments (10.0)
+ * m1 expects 'penUp
+ * }
+ * inSequence {
+ * m2 expects 'setPosition withArguments(1.0, 1.0)
+ * m2 expects 'turn withArguments (90.0)
+ * m2 expects 'forward withArguments (1.0)
+ * m2 expects 'getPosition returning (2.0, 1.0)
+ * }
+ *
+ * m2.setPosition(1.0, 1.0)
+ * m1.setPosition(0.0, 0.0)
+ * m1.penDown
+ * m2.turn(90.0)
+ * m1.forward(10.0)
+ * m2.forward(1.0)
+ * m1.penUp
+ * expect((2.0, 1.0)) { m2.getPosition }
+ * }}}
+ */
+package object borachio

0 comments on commit 53d5f4a

Please sign in to comment.
Something went wrong with that request. Please try again.