Skip to content

Instantly share code, notes, and snippets.

@cardil
Last active February 13, 2016 22:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cardil/244e839008a649de4033 to your computer and use it in GitHub Desktop.
Save cardil/244e839008a649de4033 to your computer and use it in GitHub Desktop.
An example of proposed JavaSpec as a direct port of RSpec
import pl.wavesoftware.exampleapp.MainController
import static pl.wavesoftware.jspec.DSL.*
describe(MainController, {
let 'instance', { describedClass.newInstance }
sharedExamples('not throwing any errors', {
it { expect { subject }.notTo raiseError }
it { expect(subject).notTo beNull }
})
// describing #execute method of MainController
describe(MainController#execute, {
let('params', {
def map = [:]
map['url'] = url
map['method'] = 'GET'
map
})
subject { instance.execute(params) }
context('for url /', {
let 'url', { '/' }
it { isExpected.to eq '/index.html' }
})
context('for url /home', {
let 'url', { '/home' }
it { isExpected.to eq '/home.html' }
})
})
// describing #configure method of MainController
describe(MainController#configure, {
subject { instance.configure() }
itBehavesLike 'not throwing any errors'
})
})
class JavaSpec {
private static final String DESCRIBE = 'describe'
private static final String CONTEXT = 'context'
protected JavaSpec parent
protected Map<String, Closure> lets = new HashMap<>()
protected Map<String, Object> letsEvaluated = new HashMap<>()
JavaSpec() {
this(null)
}
JavaSpec(JavaSpec parent) {
this.parent = parent
}
def let(String name, Closure closure) {
lets[name] = closure
if (letsEvaluated.containsKey(name)) {
letsEvaluated.remove(name)
}
}
// public for testing, should be protected
def invoke(Closure closure) {
def cloned = closure.clone()
cloned.delegate = this
cloned()
}
def describe(Object object, Closure description) {
newContext(DESCRIBE, object, description)
}
def context(Object context, Closure description) {
newContext(CONTEXT, context, description)
}
def methodMissing(String name, args) {
if (containsLet(name)) {
evaluateLet(name)
} else {
throw new MissingMethodException(name, this.class, args)
}
}
def propertyMissing(String name) {
if (containsLet(name)) {
evaluateLet(name)
} else {
throw new MissingPropertyException(name, this.class)
}
}
private String newContext(String name, Object context, Closure description) {
def testName = makeTestNameFromObject(context)
return testName
}
private String makeTestNameFromObject(Object object) {
if (object instanceof String) {
return object.toString()
}
Class cls
if (object instanceof Class) {
cls = object
} else {
cls = object.getClass()
}
String pkg = cls.getPackage().getName()
String replaced = pkg.replaceAll(/\.([a-z])/) { all, first ->
first.toUpperCase()
}
String capitalized = replaced.capitalize()
String.format("%s%sContext", capitalized, cls.getSimpleName())
}
private boolean containsLet(String name) {
lets.containsKey(name)
}
private Object evaluateLet(String name) {
if (!letsEvaluated.containsKey(name)) {
letsEvaluated[name] = lets.get(name).call()
}
letsEvaluated[name]
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment