Groovy-grails Mocking issue. Unable to Mock - unit-testing

I have a service class method in my grails porject which uses a helper class to fetch the response as xml. The xml is then send out as the response of the service class method.
ServiceClass:-
class ItemService{
def getItem(Number) {
def HelperClass helper = new HelperClass()
def responseXml = helper.getMessage(Number)
return responseXml
}
}
I writing a test case for this method. In my test case, i wish to mock
def responseXml = helper.getMessage(Number)
The test case that i have written so far is:
class ItemServiceTest extends GroovyTestCase {
public final void testFindItem(){
def service = new ItemService()
def xml = "<Item><Number>123</Number></Item>"
def mockJobServiceFactory = new MockFor(HelperClass)
mockJobServiceFactory.demand.getMessage{ def str ->
return xml
}
service.getItem().HelperClass = mockJobServiceFactory.proxyInstance()
def item = service.getItem()("123")
assertNotNull(item)
}
but still, the mock does not return the xml that I speicified in the test case.
Any problems that you see in the above approach?...Advance Thanks

When you mock objects with MockFor, you need to surround the code that uses the mock in a use closure. Try this:
def service = new ItemService()
def xml = "<Item><Number>123</Number></Item>"
def mockJobServiceFactory = new MockFor(HelperClass)
mockJobServiceFactory.demand.getMessage{ def str ->
return xml
}
mockJobServiceFactory.use {
def item = service.getItem()("123")
assertNotNull(item)
}

Related

How to mock passwordEncoder using Spock in a Grails unit test

I could use some advice in how to mock an auto wired dependency used in a Grails unit test. I've omitted most of the unnecessary code and just given the test class and the relevant methods in the file class under test
class UserService {
def springSecurityService // spring bean
def passwordEncoder // auto wired as per
//https://stackoverflow.com/questions/33303585/spring-//security-encode-password-with- bcrypt-algorithm
.....
def passwordPreviouslyUsed(String newPassword, def userId){
def passwordExists = false
def usersPasswords = findPasswordsForUser(userId)
usersPasswords.each{ password ->
if (passwordEncoder.isPasswordValid(oldPassword, newPassword, null)) {
passwordExists = true
}
}
return passwordExists
}
.....
def findPasswordsForUser(def userId){
User foundUser = User.findById(userId)
def passwordsForUser = UserPasswords.createCriteria().list {
eq('user', foundUser)
projections{
property('password')
}
}
passwordsForUser
}
My test
class UserServiceSpec extends Specification implements DataTest, ServiceUnitTest<UserService> {
def passwordEncoder
def setupSpec() {
mockDomains User, UserPasswords
}
def setup() {
def stubPasswordEncoder = Stub(passwordEncoder) {
isPasswordValid(_, _, _) >> true
}
service.passwordEncoder = stubPasswordEncoder
}
void "test for user passwordPreviouslyUsed"() {
given: "a user already exists"
setup()
service.createNewUser("testName", "testy#test.com", "Secret1234" )
//^(does some validation, then User.save())
User foundUser = User.findByEmail("testy#test.com")
foundUser.fullName == "testName"
long testUserId = foundUser.id
and: "we update the password for that user, and it to the userPasswords"
UserPasswords newUserPassword = new UserPasswords(
user: foundUser,
password: "newPassword1"
)
newUserPassword.save()
//use passwordPreviouslyUsed method to check a string with the same value as the
//previously
//updated password to check if it has already been used
when: "we check if the password has been used before"
def response = service.passwordPreviouslyUsed("newPassword1", fundsyId)
then:
response == true
}
Without stubbing or mocking this dependency, I get the error
Cannot invoke method isPasswordValid() on null object
I tried to stub password encoder and have it return true
def stubPasswordEncoder = Stub(passwordEncoder) {
isPasswordValid(_, _, _) >> true
}
service.passwordEncoder = stubPasswordEncoder
But this gives an error message:
Stub in 'spock.mock.MockingApi' cannot be applied to '(java.lang.Object, groovy.lang.Closure)'
Is there any way to mock this dependency with Spock?
Stub and Mock take a class - you're giving it an instance that is null - hence the exception.
You should be able to mock it as so:
def mockPasswordEncoder = Mock(PasswordEncoder)
// note this is the class
// org.springframework.security.crypto.password.PasswordEncoder
I tried enrichelgeson's approach, and it worked!
I first imported PasswordEncoder to the test class
import org.springframework.security.crypto.password.PasswordEncoder
then implemented the normal mocking procedure. I was initially confused because they class under test just implicitly created an instance of the class by defining it.
def stubPasswordEncoder = Stub(PasswordEncoder) {
isPasswordValid(_, _, _) >> true
}
service.passwordEncoder = stubPasswordEncoder
I also found another solution that didn't require mocking
service.passwordEncoder = [ isPasswordValid: { String rawPass, String salt, Null -> true } ]
Both approaches work fine. Thanks for the help!

Grails Test mockFor java.util.Calendar.getInstance()

I am trying to mock a Calendar on grails 2.2.2 unit test using grails.test.mixin
.mockFor but I have the following error:
No more calls to 'getInstance' expected at this point. End of demands.
Does anyone know if this is possible to mock Calendar?
The test class:
#TestFor(FechaService)
class FechaServiceTests {
void testGetMesesCrearMetrica() {
given:
def cal = Calendar.getInstance().set(Calendar.MONTH, 0)
def mockCalendar = mockFor(Calendar)
mockCalendar.demand.static.getInstance{-> cal}
mockCalendar.createMock()
when:
def meses = service.getMesesCrearMetrica()
...
}
}
The service method:
def getMesesCrearMetrica(){
def meses = [:]
for(def mes : Meses.values()){
if(mes.value -1 == Calendar.getInstance().get(Calendar.MONTH)) break
meses[mes.value] = mes.name()
}
return meses
}
You could change the signature of the method under test so that it accepts a Calendar as an argument.
Failing that, I would also try using metaClass.
#ConfineMetaClassChanges(Calendar)
void testGetMesesCrearMetrica() {
given:
def cal = Calendar.getInstance()
cal.set(Calendar.MONTH, 0)
Calendar.metaClass.static.getInstance = { cal }
when:
def meses = service.getMesesCrearMetrica()
...
}

How to mock springSecurityService in an unit test

I am unit testing a Grails controller method that internally creates an user instance. User domain class uses the springSecurityService of the Spring Security plugin to encode the password before inserting it into the database.
Is there a way to mock that springSecurityService from my unit test in order to get rid of that error?
Failure: Create new individual member(MemberControllerSpec)
| java.lang.NullPointerException: Cannot invoke method encodePassword() on null object
Please find my unit test below.
#TestMixin(HibernateTestMixin)
#TestFor(MemberController)
#Domain([User, IndividualPerson])
class MemberControllerSpec extends Specification {
void "Create new individual member"() {
given:
UserDetailsService userDetailsService = Mock(UserDetailsService)
controller.userDetailsService = userDetailsService
def command = new IndividualPersonCommand()
command.username = 'scott#tiger.org'
command.password = 'What ever'
command.firstname = 'Scott'
command.lastname = 'Tiger'
command.dob = new Date()
command.email = command.username
command.phone = '89348'
command.street = 'A Street'
command.housenumber = '2'
command.postcode = '8888'
command.city = 'A City'
when:
request.method = 'POST'
controller.updateIndividualInstance(command)
then:
view == 'createInstance'
and:
1 * userDetailsService.loadUserByUsername(command.username) >> null
and:
IndividualPerson.count() == 1
and:
User.count() == 1
cleanup:
IndividualPerson.findAll()*.delete()
User.findAll()*.delete()
}
}
One way to mock a service is to use Groovy's MetaClass
import grails.test.mixin.Mock
import grails.plugin.springsecurity.SpringSecurityService
...
#Mock(SpringSecurityService)
class MemberControllerSpec extends Specification {
def setupSpec() {
SpringSecurityService.metaClass.encodePassword = { password -> password }
}
def cleanupSpec() {
SpringSecurityService.metaClass = null
}
....
In this example, the call to SpringSecurityService.encodePassword() will simply return the password in plain text.
An approach using Mocks is discussed here.
You can to use this code to encode password in User:
def beforeInsert() {
encodePassword()
}
def beforeUpdate() {
if (isDirty('password')) {
encodePassword()
}
}
protected void encodePassword() {
password = springSecurityService?.passwordEncoder ? springSecurityService.encodePassword(password) : password
}
When springSecurityService is null, encodePassword is not called and NPE is not raised
When you use controller unit test with spring security rest plugin in Grails v4/v3, if your controller method reference springSecurityService methods like 'athenticatedUser', there will be NullPointException, because springSecurityService is not autowired into the spring application context.
Add code like below, you can inject springSecurityService and mock it's methods.
class GuessControllerSpec extends Specification implements ControllerUnitTest<GuessController> {
#Override
Closure doWithSpring() {
return {
// mock method
SpringSecurityService.metaClass.getCurrentUser = {return new User()}
// inject into spring context
springSecurityService(SpringSecurityService)
}
}
...
}

How to mock a HttpServletRequest's BufferedReader payload in Grails/Spock

I have a Grails controller that expects an XML payload.
I fetch the XML payload like this in a Grails controller.
def xmlPayload = request.reader.text
That part works fine, but I'm struggling to mock this payload in a unit test.
I've tried both of the following, but the debugger is showing 'request.reader' to be null in both approaches.
Approach #1:
void "test controller method"(){
setup:
def mockBufferedReader = Mock( BufferedReader )
mockBufferedReader.getText() >> '<hello/>'
request.getReader() >> mockBufferedReader
....
Approach #2:
void "test controller method"(){
setup:
def mockBufferedReader = Mock( BufferedReader )
mockBufferedReader.getText() >> '<hello/>'
request.metaClass.getReader = { -> mockBufferedReader }
....
'request' in a unit test is a GrailsMockHttpServletRequest, so I presumed I could mock its methods like this (3rd line of both approaches), but so far no luck.
Thanks for any ideas.
You can do:
class EchoController {
def echo () {
render (request.reader.text)
}
}
#TestFor(EchoController)
class EchoSpec extends Specification {
def "echos XML data" () {
request.XML = '<hello/>'
when:
controller.echo ()
then:
response.text == '<hello/>'
}
}
See Testing XML and JSON Requests in Unit Testing Controllers.
If you only need to provide contents for a request, then you don't need to mock anything.
def "Spock works as expected"() {
given:
def request = new GrailsMockHttpServletRequest(content: '<hello/>')
when:
def result = request.getReader().getText()
then:
result == '<hello/>'
}
One purpose of such Mock classes (as in Spring Test etc.) is to avoid explicit mocking with external libraries.

how to inject TagLib MockObjects in Grails Controller Unit test cases?

i have tagLib like this:
static namespace = 'j2'
def brandMessage = { attrs, body ->
def brand = ConfigurationHolder.config.j2.brand
def messageCode = (brand ? brand+".":"") + attrs.code
def defaultCode = attrs.default ?: attrs.code
out << message(code:messageCode, default:message(code:attrs.code,default:defaultCode))
}
and using in :
public static def translate = {code,Object[] args->
def dflt = (args.size()>0?args[0]:"");
def taglib = ApplicationHolder.application?.getMainContext()?.getBean("com.j2.taglib.BrandMessageTagLib")
def translatedValue = taglib?.brandMessage(code:code,default:dflt)?:""
return translatedValue
}
in controller we are using :
flash.message = I18nUtils.translate('admin.groups.delete.success')
while running the app its working fine. But when we are creating the Unit test case for the controller it throwing the error message like this:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'com.j2.taglib.BrandMessageTagLib' is defined
but i defined this in the Test class like this:
defineBeans {
myService(BrandMessageTagLib)
}
def beanName=applicationContext.getBean("myService")
log.info("beanName->"+beanName)
def mockMyTagLib = mockFor(BrandMessageTagLib)
mockMyTagLib.demand.brandMessage(1) {code, defaultMessage ->
def defCode = new MarkupBuilder(new StringWriter())
defCode.applyTemplate('<j2:brandMessage code="admin.groups.delete.success"')
}
controller.brandMessageTagLib = mockMyTagLib.createMock()
Even this is also same errormessage throwing.
anybody have idea is a greate helpfull.
Thanks
arnagendla