blob: e54348243a32421fda664c300c262147de67fb6d [file] [log] [blame]
package ioc.specs
import org.apache.commons.lang.StringUtils
import org.apache.tapestry5.ioc.internal.services.TextTransformer
import org.apache.tapestry5.ioc.services.AspectDecorator
import org.apache.tapestry5.plastic.MethodAdvice
import org.apache.tapestry5.plastic.MethodInvocation
import spock.lang.Shared
interface Subject {
void advised();
void notAdvised();
}
interface ArraysSubject {
String[] operation(String[] inputs);
}
class AspectInterceptorBuilderImplSpec extends AbstractSharedRegistrySpecification {
@Shared
private AspectDecorator decorator
def setupSpec() {
decorator = getService AspectDecorator
}
def "ensure that non-advised methods are not passed through the MethodAdvice object"() {
Subject delegate = Mock()
MethodAdvice advice = Mock()
def builder = decorator.createBuilder Subject, delegate, "<Subject>"
builder.adviseMethod Subject.getMethod("advised"), advice
Subject interceptor = builder.build()
when:
interceptor.advised()
then:
1 * advice.advise(_) >> { MethodInvocation mi ->
assert mi.method.name == "advised"
mi.proceed()
}
1 * delegate.advised()
0 * _
when:
interceptor.notAdvised()
then:
1 * delegate.notAdvised()
0 * _
}
def "failure when advising a method that is not in the service interface"() {
Subject delegate = Mock()
MethodAdvice advice = Mock()
def builder = decorator.createBuilder Subject, delegate, "<Subject>"
when:
builder.adviseMethod Runnable.getMethod("run"), advice
then:
IllegalArgumentException e = thrown()
e.message == "Method public abstract void java.lang.Runnable.run() is not defined for interface interface ioc.specs.Subject."
}
def "multiple advice for single method is processed in order"() {
TextTransformer delegate = Mock()
MethodAdvice stripFirstLetter = Mock()
MethodAdvice reverse = Mock()
def builder = decorator.createBuilder TextTransformer, delegate, "<TextTransformer>"
def method = TextTransformer.getMethod "transform", String
builder.adviseMethod method, stripFirstLetter
builder.adviseMethod method, reverse
TextTransformer advised = builder.build()
when:
def result = advised.transform "Tapestry"
then:
result == "[yrtsepa]"
1 * stripFirstLetter.advise(_) >> { MethodInvocation mi ->
assert mi.getParameter(0) == "Tapestry"
mi.setParameter 0, mi.getParameter(0).substring(1)
mi.proceed()
}
1 * reverse.advise(_) >> { MethodInvocation mi ->
assert mi.getParameter(0) == "apestry"
mi.setParameter 0, StringUtils.reverse(mi.getParameter(0))
mi.proceed()
}
1 * delegate.transform(_) >> { it }
}
def "arrays are allowed as method parameters and return values"() {
ArraysSubject delegate = Mock()
MethodAdvice advice = Mock()
def builder = decorator.createBuilder ArraysSubject, delegate, "unused"
builder.adviseAllMethods advice
ArraysSubject advised = builder.build()
when:
def result = advised.operation(["Fred", "Barney"] as String[])
then:
1 * advice.advise(_) >> { MethodInvocation it ->
String[] inputs = it.getParameter(0)
it.setParameter 0, inputs.collect({it.toUpperCase() }) as String[]
it.proceed()
def index = 0
it.setReturnValue it.getReturnValue().collect({ value -> "${index++}:$value" }) as String[]
}
1 * delegate.operation(_) >> { it[0] }
result.class == ([] as String[]).class
result.asType(List) == ["0:FRED", "1:BARNEY"]
}
}