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()
...
}
Related
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!
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)
}
}
...
}
I'm trying to do a Unit test on this controller. I'm new to this sort of testing so I dont know from where do I start and how to test things that are needed to be tested, like user, render view.)
class ShoppingCartController {
def shoppingCartWebshopService
def shoppingCartService
def springSecurityService
def checkoutOperaService
def databaseService
def dodAdresaService
def payingOrder(SetShop1Command cmd) {
def user = springSecurityService.isLoggedIn() ? springSecurityService.currentUser.sifpartnera : null
def tempAdrese = databaseService.getAdrese(user)
def adrese = []
tempAdrese.each{
adrese.add(it.adresa)
}
if (cmd.hasErrors()) {
render(view: 'OrderChoseAddress', model: [cmd : cmd, params : params, adrese: adrese ])
}
def inputUnAdrese = params.inputUnAdrese
[inputUnAdrese: inputUnAdrese, adrese: adrese]
}
This is my test
#Mock([SpringSecurityService,DatabaseService])
#TestFor(ShoppingCartController)
class ShoppingCartControllerTests {
void testPayingOrder(){
when:
// params.user = 19
// user.equals(id)
// println user
// controller.OrderChoseAddress()
controller.params.user = "admin"
controller.databaseService = new DatabaseService()
then:
assert model.adrese != null
}
Am getting the following error message when testing the controller - see below for code.
How can I correct this?
When I invoke the service method from the controller (run-app) and it works fine.
Exception:
groovy.lang.MissingMethodException: No signature of method:
grails.test.GrailsMock.isOk() is applicable for argument types:
(java.lang.String) values: [H] at ...VControllerSpec.test
something(VControllerSpec.groovy:)
class: VControllerSpec
import grails.test.mixin.TestFor
import spock.lang.Specification
#TestFor(VController)
#Mock(VService)
class VControllerSpec extends Specification {
void "test something"() {
given:
def vServiceMock = mockFor(VService)
vServiceMock.demand.isOk { String yeah -> return true }
controller.vService = vServiceMock.createMock()
when:
def isO = vServiceMock.isOk("H")
then:
isO == true
}
}
class:VService
import grails.transaction.Transactional
#Transactional
class VService {
def isOk = { String yeah ->
def isO = false
return isO
}
}
Thanks,
Steve
Assuming there is an action in VController as:
def myAction() {
vService.isOk('Hello')
}
below test should pass
void 'test service'() {
given:
def vServiceMock = mockFor(FormatService)
vServiceMock.demand.isOk { String yeah -> return true }
controller.vService = vServiceMock.createMock()
when:
def isO = controller.myAction()
then:
isO == true
}
There are few things to optimize here including using a method isOk instead of a closure as best practices.
One is not expected to test a method which is being mocked. When we mock a method, we just assume its implementation is correct and has already been tested (in some other unit test). The purpose of mocking is to limit our focus of testing to limited lines of code (mostly commonly one method), in your case the your controller action. So the above test case could have been written as:
Assuming your action is like this:
def myAction(){
[iso: vServiceMock.isOk()] // assuming isOk returns boolean true
}
void "test myAction"() {
given:
def vServiceMock = mockFor(VService)
vServiceMock.demand.isOk { String yeah -> return true }
controller.vService = vServiceMock.createMock()
when:
def model = controller.myAction()
then:
model.iso //you can skip comparison with true
}
Total 'testing newbie' wanting to test the addJsFile method of my custom TagLib. What am I missing?
TagLib:
import com.company.group.application.helper.Util
...
class MyTagLib {
static namespace = 'mytag'
def util
...
def addJsFile = {
if (util.isSecureRequest(request)) {
out << '<script src="https://domain.com/jsfile.js"></script>'
} else {
out << '<script src="http://domain.com/jsfile.js"></script>'
}
}
}
Test (as far as I could get):
import org.springframework.http.HttpRequest
import com.company.group.application.helper.Util
#TestFor(MyTagLib)
class MyTagLibTests {
def util
...
void testAddJsFileSecure() {
def mockUtil = mockFor(Util)
mockUtil.demand.isSecureRequest() { HttpRequest request -> true }
def jsCall = applyTemplate('<mytag:addJsFile />')
assertEquals('<script src="https://domain.com/jsfile.js"></script>', jsCall)
}
void testAddJsFileNotSecure() {
def mockUtil = mockFor(Util)
mockUtil.demand.isSecureRequest() { HttpRequest request -> false }
def jsCall = applyTemplate('<mytag:addJsFile/>')
assertEquals('<script src="http://domain.com/jsfile.js"></script>', jsCall)
}
}
Util isSecureRequest
boolean isSecureRequest(request) {
return [true or false]
}
Error
org.codehaus.groovy.grails.web.taglib.exceptions.GrailsTagException: Error executing tag <mytag:addJsFile>: Cannot invoke method isSecureRequest() on null object
You need to set the mocked util in tagLib in order to use it.
void testAddJsFileSecure() {
def mockUtilControl = mockFor(Util)
mockUtilControl.demand.isSecureRequest() { HttpRequest request -> true }
//"tagLib" is the default bind object provided
//by the mock api when #TestFor is used
tagLib.util = mockUtilControl.createMock()
//Also note mockFor() returns a mock control
//which on createMock() gives the actual mocked object
def jsCall = applyTemplate('<mytag:addJsFile />')
assertEquals('<script src="https://domain.com/jsfile.js"></script>', jsCall)
//In the end of test you can also verify that the mocked object was called
mockUtilControl.verify()
}
You would not need def util in the test then.