grails spock test mock CommonsMultipartFile - unit-testing

I've following old method written in code, which is for accessing request object in service class such as:
def someServiceMethod() {
....
def webUtils = WebUtils.retrieveGrailsWebRequest()
def request = webUtils.getCurrentRequest()
MultipartHttpServletRequest mpr = (MultipartHttpServletRequest) request
CommonsMultipartFile file = (CommonsMultipartFile) mpr.getFile("file")
....
}
This is my unit test code for serivce class.
#TestFor(SomeService)
class SomeServiceSpec extends Specification {
void "test someServiceMethod"() {
given:
MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest()
FileInputStream inFile = new FileInputStream("./test-data/Hiearchy-003.xlsx") //valid file path
def multipartFile = new GrailsMockMultipartFile('file', 'file.xls', 'multipart/form-data', inFile)
request.addFile(multipartFile)
GrailsWebRequest webRequest = new GrailsWebRequest(
request,
new MockHttpServletResponse(),
new MockServletContext()
)
request.setAttribute(GrailsApplicationAttributes.WEB_REQUEST,webRequest)
RequestContextHolder.setRequestAttributes(webRequest);
when:
def result = service.someServiceMethod()
then:
result != null
//some more assertions
//..
}
}
I'm stuck with following error.
| Failure: test someServiceMethod(SomeServiceSpec)
| org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'org.codehaus.groovy.grails.plugins.testing.GrailsMockMultipartFile#6ae8e5dd' with class 'org.codehaus.groovy.grails.plugins.testing.GrailsMockMultipartFile' to class 'org.springframework.web.multipart.commons.CommonsMultipartFile'
Anybody faced such issue before in grails unit test?

Instead of : GrailsMockMultipartFile,
use: org.springframework.mock.web.MockMultipartFile.

I just realised following line is just unnecessary if we use input stream direct it should not be problem hence solved my issue..
CommonsMultipartFile file = (CommonsMultipartFile) mpr.getFile("file")

Related

Grails String.encodeAsBase64() Fails in Spock Tests

This code works fine when I run it in Grails.
String getLoginToken() {
generatePassword()
passwordExpired = false
[email, password].join(',').encodeAsBase64()
}
However, this Spock test fails
def "test getLoginToken"() {
setup:
String email = "bacon#eggs.edu"
Person person = new Person(email: email)
when:
String token = person.getLoginToken()
then:
token.decodeBase64() == "$email,$person.password"
}
with the following exception
| Failure: test getLoginToken(com.campuscardtools.myphotoid.PersonSpec)
| groovy.lang.MissingMethodException: No signature of method: java.lang.String.encodeAsBase64() is applicable for argument types: () values: []
Possible solutions: decodeBase64()
at com.campuscardtools.myphotoid.Person$$EPFScS6i.getLoginToken(Person.groovy:140)
at com.campuscardtools.myphotoid.PersonSpec.test getLoginToken(PersonSpec.groovy:68)
My understanding is that Groovy provides the encodeAsBase64() on the String class (see: http://mrhaki.blogspot.com/2009/11/groovy-goodness-base64-encoding.html), so why doesn't this work in the unit test?
Rather than
"Blah".encodeAsBase64()
You need
"Blah".encodeBase64()
Without the 'As'
You could also include a mockCodec for the method you're using.
and: "add the Base64 codec"
mockCodec(org.codehaus.groovy.grails.plugins.codecs.Base64Codec)
This works, but I fells like a bad hack. Surely there must be cleaner solution:
def cleanup () {
String.metaClass = null
}
def "test getLoginToken"() {
setup:
String email = "bacon#eggs.edu"
Person person = new Person(email: email)
String encoded = null
and:
String.metaClass.encodeAsBase64 {
encoded = delegate
return delegate
}
when:
String token = person.getLoginToken()
then:
token == "$email,$person.password"
encoded == "$email,$person.password"
}

How to test a grail service that has resultTransformer within withCriteria(Spock).?

In the below class, I just need RevShareFormula.withCriteria to return a result,
but getting the exception in resultTransformer() method.
Can anyone tell me how to Mock the below method so that i get some result from withCriteria
Here is the class:
class PartnerFinancialService {
def getPartnerPayeeRevenuShareDetails(long partnerPayeeId, def contextTypeCode) {
def partnerPayeesRevShareFormula = RevShareFormula.withCriteria {
resultTransformer(CriteriaSpecification.ALIAS_TO_ENTITY_MAP)
createAlias('partnerRevShareConfig', 'partnerRevShareConfig')
createAlias('pricingModel', 'pricingModel')
createAlias('partnerRevShareConfig.revshareCategory', 'revshareCategory')
and {
eq("revshareCategory.payeeProfileId", partnerPayeeId)
eq("revshareCategory.referenceContextTypeCode", contextTypeCode)
isNull("partnerRevShareConfig.revshareValidToDate")
}
projections {
property("id", "formulaId")
property("pricingModel.id", "pricingModelId")
property("pricingModel.pricingName", "pricingName")
property("pricingModel.pricingType", "pricingType")
..
..
}
}
}
Here is the test class
#TestFor(PartnerFinancialService)
#Mock(RevShareFormula)
class PartnerFinancialServiceSpec extends Specification {
void "test getPartnerPayeeRevShareDetails"() {
def partnerPayeeRevShare = new PartnerRevShareConfig()
partnerPayeeRevShare.id = 1
def revShareModel = new PricingModel();
revShareModel.id = 1
def partnerPayeeRevShareFormula = new RevShareFormula();
partnerPayeeRevShareFormula.id=5
partnerPayeeRevShareFormula.pricingModel = revShareModel
partnerPayeeRevShareFormula.partnerRevShareConfig = partnerPayeeRevShare
partnerPayeeRevShareFormula.revshareFormula = "revshare*10"
partnerPayeeRevShareFormula.revshareTierHighValue = 0
partnerPayeeRevShareFormula.revshareTierLowValue= 0
RevShareFormula.metaClass.static.withCriteria = {partnerPayeeRevShareFormula}
when:
def result = service.getPartnerPayeeRevenuShareDetails(1,"PKG")
then:
//assert result.pricingModel.id == 1
println "Succesfully Fetched from DB"
}
}
Getting the following exception.
<testcase classname="com.orbitz.dat.partners.PartnerFinancialServiceSpec" name="test getPartnerPayeeRevShareDetails" time="0.039">
<error message="No signature of method: com.orbitz.dat.partners.PartnerFinancialService.resultTransformer() is applicable for argument types: (org.hibernate.transform.AliasToEntityMapResultTransformer) values: [org.hibernate.transform.AliasToEntityMapResultTransformer#3632aa4]" type="groovy.lang.MissingMethodException">groovy.lang.MissingMethodException: No signature of method: com.orbitz.dat.partners.PartnerFinancialService.resultTransformer() is applicable for argument types: (org.hibernate.transform.AliasToEntityMapResultTransformer) values: [org.hibernate.transform.AliasToEntityMapResultTransformer#3632aa4]
at com.orbitz.dat.partners.PartnerFinancialService.$tt__getPartnerPayeeRevenuShareDetails_closure24(PartnerFinancialService.groovy:39)
at grails.gorm.CriteriaBuilder.invokeClosureNode(CriteriaBuilder.java:1093)
at grails.gorm.CriteriaBuilder.invokeMethod(CriteriaBuilder.java:314)
at org.grails.datastore.gorm.GormStaticApi.withCriteria_closure11(GormStaticApi.groovy:304)
at org.grails.datastore.mapping.core.DatastoreUtils.execute(DatastoreUtils.java:302)
at org.grails.datastore.gorm.AbstractDatastoreApi.execute(AbstractDatastoreApi.groovy:37)
at org.grails.datastore.gorm.GormStaticApi.withCriteria(GormStaticApi.groovy:303)
at com.orbitz.dat.partners.PartnerFinancialService.$tt__getPartnerPayeeRevenuShareDetails(PartnerFinancialService.groovy:38)
at com.orbitz.dat.partners.PartnerFinancialServiceSpec.test getPartnerPayeeRevShareDetails(PartnerFinancialServiceSpec.groovy:71)
Use an integration test. Never test ORM code with unit tests. I know it's slower and the experience is less enjoyable, but you are fooling yourself if you think that you are actually testing something related to database queries with this test. You are testing the testing framework of grails (the in-memory GORM implementation)

Failing Unit Test In Grails 1.3.7 Spock

I have this piece of code in a controller:
def update = {
Map model = [:]
model.foo = params.foo
model.bar = params.bar
def result = ""
MyObject obj = MyObject.findWhere(bar:bar, foo:foo)
MyObjectService.updateObj(model,obj)
result = true
render result as JSON
}
And this simple unit test:
def 'controller update'() {
given:
controller.params.foo = foo
controller.params.bar = bar
MyObject obj = new MyObject(bar:bar, foo:foo)
mockDomain(MyObject,[obj])
when:
controller.update()
then:
1 * MyObject.findWhere(bar:bar, foo:foo) >> obj
1 * MyObjectService.updateObj(model,obj)
and:
def model = JSON.parse(controller.response.contentAsString)
model == true
where:
foo = "0"
bar = "1"
}
Now this is failing by and it is telling me that, "not static method findWhere is applicable..." for those arguments. That "MyObject" is just an orm class, and when I run that application everything seems to be working fine, but the test is failing.
My logic is this:
I want to count how many times the findWhere and updateObj methods are call and I am also mocking their response. So findWhere will return the object I already mocked, and pass it on to the service.
Any ideas why this is failing ?
For mocking static methods you should use Spock's GroovyStub class which introduced in v0.7.

Groovy HTTPBuilder Mocking the Client

This question is closely related to this question. The difference is that I'd like to follow the recommended approach of mocking the client. So, I have the following HTTPBuilder defined:
protected readUrl() {
def http = new HTTPBuilder("http://example.com")
def status = http.request(Method.GET, ContentType.JSON) {req ->
response.success = {resp, json ->
result = json.toString()
new Success<String>(result)
}
response.'401' = {resp ->
final String errMsg = "Not Authorized"
new Failed(Failable.Fail.ACCESS_DENIED, errMsg)
}
response.failure = {resp ->
final String errMsg = "General failure ${resp.statusLine}"
new Failed(Failable.Fail.UNKNOWN, errMsg)
}
}
}
What I'd like to do is find a way to unit test this code block. I wanted to mock the response so I could specifically set the response codes, if possible. Could someone please show me a way to do this?
This is my prefered solution:
class MockHTTPBuilder{
MockHTTPBuilder(string){}
MockHTTPBuilder(){}
def pleaseFail = false
def mockData = []
def request(a, b, c){
if(pleaseFail) [status:'500',data: mockData ?: "It failed :("]
else [status:'200',data: mockData ?: "Yay :)"]
}
}
Here's some sample usages: http://groovyconsole.appspot.com/script/760001
Alternatively, you can metaprogram the actual httpClient instance and make it behave as expected(forcebly failing or passing during test-time) but that's a little bit more complicated.

Second Use of GrailsApplication Mock in Service Test Fails

I'm unit testing a Grails service and using Mocks to mock out calls to the
GrailsApplication class. I have one test that succeeds but when I try
subsequent tests they fail. I am using demand to mock the isDomainClass
method. I have tried copying and pasting the code from the test that
succeeds to the test method that fails but the second time the same code
runs it fails saying that no more calls to isDomainClass are expected. I'm
suspecting some leakage between the methods but I can't see where it is.
Things I've tried already:
Running the tests from the command line (I'm running the tests under SpringSource Tool Suite version 2.7.0.201105292341-M2.)
Moving the failing test to a different test class (the test that runs first succeeds)
Changing the number range in the demands clause to 1..5 (second test still fails)
Here is the relevant portions of my test case:
package simulation
import grails.test.*
import org.joda.time.*
import org.codehaus.groovy.grails.commons.GrailsApplication
class ObjectSerializationServiceTests extends GrailsUnitTestCase {
def objectSerializationService
protected void setUp() {
super.setUp()
objectSerializationService = new ObjectSerializationService()
}
protected void tearDown() {
super.tearDown()
objectSerializationService = null
}
void testDomainObjectSerialization() {
def otherControl = mockFor(GrailsApplication)
otherControl.demand.isDomainClass(1..1) {true}
otherControl.demand.getDomainClass(1..1) {className ->
assert className == "simulation.TestDomainClass"
TestDomainClass.class
}
objectSerializationService.grailsApplication = otherControl.createMock()
def now = new DateTime()
def testObject = new TestDomainClass([id:57, someOtherData:"Some Other
Data", theTime:now])
def testInstances = [testObject]
mockDomain(TestDomainClass, testInstances)
def serialized = objectSerializationService.serializeObject(testObject)
def deserialized =
objectSerializationService.deserializeObject(serialized)
assert deserialized == testObject
assert serialized.objectType == SerializedObject.ObjectType.DOMAIN
otherControl.verify()
}
void testSerializableSerialization() {
def otherControl = mockFor(GrailsApplication)
otherControl.demand.isDomainClass(1..1) {true}
otherControl.demand.getDomainClass(1..1) {className ->
assert className == "simulation.TestDomainClass"
TestDomainClass.class
}
objectSerializationService.grailsApplication = otherControl.createMock()
def now = new DateTime()
def testObject = new TestDomainClass([id:57, someOtherData:"Some Other
Data", theTime:now])
def testInstances = [testObject]
mockDomain(TestDomainClass, testInstances)
def serialized = objectSerializationService.serializeObject(testObject)
def deserialized =
objectSerializationService.deserializeObject(serialized)
assert deserialized == testObject
assert serialized.objectType == SerializedObject.ObjectType.DOMAIN
otherControl.verify()
}
}
And the output:
Testcase: testDomainObjectSerialization took 0.943 sec
Testcase: testSerializableSerialization took 0.072 sec
FAILED
junit.framework.AssertionFailedError: No more calls to 'isDomainClass'
expected at this point. End of demands.
at grails.test.MockClosureProxy.doBeforeCall(MockClosureProxy.java:66)
at grails.test.AbstractClosureProxy.call(AbstractClosureProxy.java:74)
at
simulation.ObjectSerializationService.serializeObject(ObjectSerializationService.groovy:20)
at simulation.ObjectSerializationService$serializeObject.call(Unknown
Source)
at
simulation.ObjectSerializationServiceTests.testSerializableSerialization(ObjectSerializationServiceTests.groovy:68)
I got a similar error trying to use mockFor on jms Message interface in multiple test cases.
I got around it by creating a custom interface that extends from the interface that needs to be mocked. You would use the custom interface to create the mock.
e.g.
private interface GrailsApplicationTest1 extends GrailsApplication(){}
testOne(){
def control = mockFor(GrailsApplicationTest1)
//...rest of code
}
private interface GrailsApplicationTest2 extends GrailsApplication(){}
testTwo(){
def control = mockFor(GrailsApplicationTest2)
//...rest of code
}
//add more private interfaces for additional test cases..
I'm not exactly sure why but I think the mockFor behaves differently between interfaces and non-interfaces. But that's just a wild guess.