Groovy 如何编写自定义Spock交互迷你DSL来测试我的邮件发送?
我很难为我的spock测试编写简洁易读的自定义交互 以下是我目前掌握的情况:Groovy 如何编写自定义Spock交互迷你DSL来测试我的邮件发送?,groovy,spock,Groovy,Spock,我很难为我的spock测试编写简洁易读的自定义交互 以下是我目前掌握的情况: class FunctionTestMailSpec extends Specification { ... def "process functional test email"(){ ... stuff that processes the mail and ends up calling sendMailSvc.sendEmail() ... then: "mail
class FunctionTestMailSpec extends Specification {
...
def "process functional test email"(){
...
stuff that processes the mail and ends up calling sendMailSvc.sendEmail()
...
then: "mail should be sent to the expected address"
// (A)
1 * sendMailSvc.sendEmail(testMsg.sesMessageId, _ as Message ) >> {
msgId, Message msg ->
assert msg.subject == testMsg.variables.subject
assert msg.to.flatten() == [mime.parseMailbox(keywordRealAddress)]
}
// (B)
1 * sendMailSvc.sendEmail(testMsg.sesMessageId, _ as Message ) >> {
msgId, Message msg -> assertMessage(
msg, testMsg.variables.subject, keywordRealAddress)
}
// (C)
1 * sendMailSvc.sendEmail(testMsg.sesMessageId, _ as Message ) >> {
String msgId, Message msg ->
new MessageAssertion().
withSubject(testMsg.variables.subject).
withTo(keywordRealAddress).apply(msgId, msg)
}
// (D)
// GroovyCastException: Cannot cast object 'org.codehaus.groovy.runtime.MethodClosure@1e4c4fda' with class 'org.codehaus.groovy.runtime.MethodClosure' to class 'com.amazonaws.services.simpleemail.model.SendRawEmailResult'
1 * sendMailSvc.sendEmail(testMsg.sesMessageId, _ as Message ) >>
new MessageAssertion().
withSubject(testMsg.variables.subject).
withTo(keywordRealAddress).&apply
}
void assertMessage(
Message message,
String subject,
String[] to
){
assert message.subject == subject
assert message.to.flatten() == to.collect{mime.parseMailbox(it)}
}
}
class MessageAssertion implements BiFunction<String, Message, SendRawEmailResult> {
String sesMessageId
String subject
Mailbox[] to = []
MimeUtil mime = new MimeUtil()
def withSubject(String subject){
this.subject = subject
this
}
def withSesMessageId(String sesMessageId){
this.sesMessageId = sesMessageId
this
}
def withTo(String[] to){
this.to = to.collect{mime.parseMailbox(it)}
this
}
@Override
SendRawEmailResult apply(String sesMessageId, Message message){
if( this.sesMessageId ){
assert sesMessageId == this.sesMessageId
}
if( this.subject ){
assert message.subject == this.subject
}
if( this.to ){
assert message.to.flatten().toArray() == this.to
}
return null
}
}
我需要做什么来定义一个DSL,它允许我编写这样的交互,或者接近它?只是一个假设
您可能可以创建这样的类:
class A{
String name_
A make(String name){
this.name_=name
return this
}
A rightShift(B b){
b.greet(name_)
return this
}
}
//aka SendRawEmailResult
abstract class B{
abstract def greet(String name)
}
//aka MessageAssertion
class C {
def asserts=[:]
Object invokeMethod(String name, Object args){
if(name.startsWith('with')){
asserts[name.substring(4)]=args
return this
}
throw new Exception("$name method not supported for ${this.getClass()}")
}
Closure apply(){
return {String x->
println "assert for `$x`"
if(asserts.Subject){
println "assert Subject here"
}
asserts.each{k,v->
println "$k : [${v.getClass()}] $v"
}
}
}
String toString(){
return "*** ${this.getClass()}${asserts}"
}
}
new A().make('world') >>
new C().withQwe('qwe123').withZte('zte456').withSubject('subj').apply()
这不管用。必须从闭包接口添加两个ctor()(与委托、“所有者”和“thisObject”有关)。但更重要的是,它失败了,出现了与(D)相同的错误,表示它无法强制转换接近SendRawEmailResult的结果(这就是被模拟的方法sendEmail()应该返回的结果)。
class A{
String name_
A make(String name){
this.name_=name
return this
}
A rightShift(B b){
b.greet(name_)
return this
}
}
//aka SendRawEmailResult
abstract class B{
abstract def greet(String name)
}
//aka MessageAssertion
class C {
def asserts=[:]
Object invokeMethod(String name, Object args){
if(name.startsWith('with')){
asserts[name.substring(4)]=args
return this
}
throw new Exception("$name method not supported for ${this.getClass()}")
}
Closure apply(){
return {String x->
println "assert for `$x`"
if(asserts.Subject){
println "assert Subject here"
}
asserts.each{k,v->
println "$k : [${v.getClass()}] $v"
}
}
}
String toString(){
return "*** ${this.getClass()}${asserts}"
}
}
new A().make('world') >>
new C().withQwe('qwe123').withZte('zte456').withSubject('subj').apply()