Reputation: 130
I'm creating a unit test for my program. I have a void method which is taking five arguments, then converting those arguments into a closure and passing it to another service to be turned into an Email and sent. The only thing I care about is the body of this email, which is stored in one of the arguments passed into this function. Is it possible to verify this argument without changing the design of my program?
I've considered using Spock style mocks, but I can't determine if I can actually mock/stub out methods in my spec-tested class or if I can only mock out dependencies.
Class myTestService
{
def outsideService
private void sendEmail (User source, String subj, String body, List to, List attachments){
outsideService.sendMail{
//blah blah
subject subj
html wrapWithDefault(body) //wrapWithDefault is a big styling document also in this function
//blah blah
}
}
int send(GrailsParameterMap params, HttpServletRequest request) {
//Parse out attachments from request and body/subject/addressee from params
//little bit of business logic to ensure that we can send emails in our system
sendEmail(source,
subject,
"$body <br /><br /> important extra information",
sendTo,
attachments)
//Send another email to the source as a receipt
sendEmail(source,
subject,
"$body extra junk $receiptBody",
source,
attachments)
}
}
I need to find out if the receipt is properly adding receiptBody. Given that I'm sending a closure out to outsideService, it's hard to just rip variables out of that, so I'm at a bit of a loss.
EDIT: in response to the answer below, I've inserted a spock style mock into my testing, but I don't think I have the semantics right, because value is storing null. void "#value contains #params.body"() { given:
//def params, request, filling in all necessary values
def value
def mailServiceMock = Mock(MailService)
mailServiceMock.sendMail(*_) >> {closure ->
closure.delegate = new Expando(
multipart:{},
from: {},
subject: {},
html: {value = it}
bcc: {}
)
closure()
}
//inform service of mock
service.mailService = mailServiceMock
when:
service.send(params, request)
then:
println("value = $value")
1 * mailServiceMock.sendMail(*_) // this should fail, since this should be called twice, but one thing at a time.
value.contains(params.body)
}
value is showing null. Any thoughts?
Upvotes: 1
Views: 1915
Reputation: 14519
You can mock your service.
This is a very simple script which mocks outsideService
to store the value received in the html
method in a script var. You should go for Spock/JUnit/YouNameIt to make this tidy.
class MyTestService
{
def outsideService
private void sendEmail (source, String subj, String body, List to, List attachments){
outsideService.sendMail{
subject subj
html "<body>$body</body>"
}
}
}
myTest = new MyTestService()
def body
myTest.outsideService = [sendMail: { closure ->
closure.delegate = new Expando(
subject: { }, //don't care
html: { body = it }
)
closure()
}]
myTest.sendEmail(null, 'my subject', 'my email body', null, null)
assert '<body>my email body</body>' == body
Upvotes: 2