Grails 3 mail plugin not working - grails

Using Grails 3 it's impossible to get an instance of mailService object, DI is not working:
build.gradle
compile "org.grails.plugins:mail:1.0.7"
testCompile "org.grails.plugins:mail:1.0.7"
application.groovy
environments {
development {
//grails.logging.jul.usebridge = true
grails.plugin.springsecurity.debug.useFilter = true
grails {
mail {
host = "main.mydomain.com"
port = 25
username = "login"
password = "password"
props = ["mail.smtp.auth":"true"]
}
}
grails.mail.default.from="noreply#mydomain.com"
}
production {
grails.logging.jul.usebridge = false
}
}
testController:
import groovy.xml.MarkupBuilder
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.security.access.annotation.Secured
#Secured(["hasRole('PERM_LOGIN')"])
class TestLogController {
def Logger logger = LoggerFactory.getLogger(this.getClass())
def mailService
def index() {
logger.info("Hello");
mailService.sendMail {
to "user#daomain.com"
subject "Hello Fred"
text "How are you?"
}
}
}
The following error occurs:
Caused by NullPointerException: Cannot invoke method sendMail() on null object
->> 18 | index in TestLogController.groovy
So mailService has not been injected properly to cotroller class or to integration test:
import grails.test.mixin.integration.Integration
import grails.util.Holders
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.context.ApplicationContext
import spock.lang.Shared
import spock.lang.Specification
#Integration
class SendMailSpec extends Specification {
#Shared Logger logger
#Shared def mailService
def setup() {
logger = LoggerFactory.getLogger(this.getClass())
ApplicationContext ctx = Holders.grailsApplication.mainContext
mailService = ctx.getBean("mailService");
}
def cleanup() {
}
void "test mailService is not null"() {
expect:
mailService !=null
}
void "test send mail"() {
expect:"mail send"
mailService.sendMail {
to "user#domain.com"
subject "Hello Fred"
text "How are you?"
}
}
}
What is a problem ??
UPDATE: It was wrong mail plugin version, this one works fine:
compile "org.grails.plugins:mail:2.0.0.RC2"

here's the current version (at the moment of writing this) to install :
compile 'org.grails.plugins:mail:2.0.0.RC6'
Here's the link to the main plugin (I don't know why google shows only the old versions) :
https://grails.org/plugins.html#plugin/mail
I hope this helps someone

Related

grails restful groovy can not resolve symbol

I am trying to learn grails by following the link: https://guides.grails.org/rest-hibernate/guide/index.html and after creating the controller ProductController as per the page's guidance I am getting the following error:
Unable to resolve class ProductService in ProductController
I new to groovy and trying to resolve the class reference by importing the necessary packages but the link does not show any imports to resolve this class. there is not explicit import statement for ProductService productService in ProductController.groovy. Here are the classes:
ProductController:
package hibernate.example
import groovy.transform.CompileStatic
import grails.rest.*
import grails.converters.*
#CompileStatic
class ProductController extends RestfulController {
static responseFormats = ['json', 'xml']
ProductController() {
super(Product)
}
ProductService productService
def search(String q, Integer max ) {
if (q) {
respond productService.findByNameLike("%${q}%".toString(), [max: Math.min( max ?: 10, 100)])
}
else {
respond([])
}
}
}
ProductControllerSpec:
package hibernate.example
import org.grails.testing.GrailsUnitTest
import spock.lang.Specification
#SuppressWarnings('MethodName')
class ProductControllerSpec extends HibernateSpec implements ControllerUnitTest<ProductController> {
def setup() {
}
def cleanup() {
}
static doWithSpring = {
jsonSmartViewResolver(JsonViewResolver)
}
void 'test the search action finds results'() {
given:
controller.productService = Stub(ProductService) {
findByNameLike(_, _) >> [new Product(name: 'Apple', price: 2.0)]
}
when: 'A query is executed that finds results'
controller.search('pp', 10)
then: 'The response is correct'
response.json.size() == 1
response.json[0].name == 'Apple'
}
}

Inject property into integration test Grails 3

How does one inject properties from the applicaiton.yml file into an integration test in grails 3.0 ?
For ex: I have this property in my applicaiton.yml
----
testing:
defaults:
startUrl: 'http://localhost:8080/'
----
In my Integration Spock test, I have the following code:
class WebpageRolesTestSpec extends Specification {
def grailsApplication
String LOGIN_URL = grailsApplication.config.getProperty('testing.defaults.startUrl')
void "test login screen prompt"() {
expect:
LOGIN_URL == 'http://localhost:8080/'
}
}
The exception i am getting is: Cannot get property 'config' on null object
You could use holders:
import grails.util.Holders
...
LOGIN_URL = Holders.config.testing.defaults.startUrl
...
Below test works for me in Grails 3.1.1, I suppose you would need a clean app.
import grails.test.mixin.integration.Integration
import grails.transaction.*
import spock.lang.*
#Integration
#Rollback
class SampleSpec extends Specification {
def grailsApplication
void "test something"() {
expect:"fix me"
grailsApplication.config.getProperty('testing.defaults.startUrl') ==
'http://localhost:8080/'
}
}

Grails - How to instantiate service in Controller when doing controller testing

I am using a service in controller. I am writing unit test for the controller but I am unable to instantiate service in controller. It is always null.
if I instantiate service using new operator in Controller testing class. The services in the service class are not instantiated.
How can I instantiate a service in testing class?
You can let Spring do it for you.
A controller that depends on a service:
// grails-app/controllers/demo/DemoController.groovy
package demo
class DemoController {
def helperService
def index() {
def answer = helperService.theAnswer
render "The answer is ${answer}"
}
}
The service:
// grails-app/services/demo/HelperService.groovy
package demo
class HelperService {
def getTheAnswer() {
42
}
}
A unit test which injects the service:
// src/test/groovy/demo/DemoControllerSpec.groovy
package demo
import grails.test.mixin.TestFor
import spock.lang.Specification
#TestFor(DemoController)
class DemoControllerSpec extends Specification {
static doWithSpring = {
helperService HelperService
}
void "test service injection"() {
when:
controller.index()
then:
response.text == 'The answer is 42'
}
}
A unit test which injects a fake version of the service:
// src/test/groovy/demo/AnotherDemoControllerSpec.groovy
package demo
import grails.test.mixin.TestFor
import spock.lang.Specification
#TestFor(DemoController)
class AnotherDemoControllerSpec extends Specification {
static doWithSpring = {
helperService DummyHelper
}
void "test service injection"() {
when:
controller.index()
then:
response.text == 'The answer is 2112'
}
}
class DummyHelper {
def getTheAnswer() {
2112
}
}

Inject services to src/groovy in Grails 3.0.9

I am trying to create an EndPoint file. So I created a file with name ServerEndPointDemo.groovy
package com.akiong
import grails.util.Environment
import grails.util.Holders
import javax.servlet.ServletContext
import javax.servlet.ServletContextEvent
import javax.servlet.ServletContextListener
import javax.servlet.annotation.WebListener
import javax.websocket.EndpointConfig
import javax.websocket.OnClose
import javax.websocket.OnError
import javax.websocket.OnMessage
import javax.websocket.OnOpen
import javax.websocket.Session
import javax.websocket.server.PathParam
import javax.websocket.server.ServerContainer
import javax.websocket.server.ServerEndpoint
import javax.websocket.EncodeException
import javax.servlet.annotation.WebListener
import java.util.concurrent.CopyOnWriteArraySet
#WebListener
#ServerEndpoint(value="/chat/test/{username}")
public class ServerEndPointDemo implements ServletContextListener {
private static HashMap<String, String> usersMap = new HashMap<String, String>();
private static final Set<ServerEndPointDemo> connections = new CopyOnWriteArraySet<>();
private String username
private Session session
#OnOpen
public void handleOpen(Session session,#PathParam("username") String user){
System.out.println("-------------------------------------");
System.out.println(session.getId() + " has opened a connection");
println "user = "+user
connections.add(this);
this.username = user
this.session = session
addUserToMap(username,session.getId())
try{
def ctx = Holders.applicationContext
chatService = ctx.chatService
}
catch (Exception e){
println "e = "+e
}
}
#OnClose
public void handleClose(Session session){
System.out.println("Session " +session.getId()+" has ended");
}
#OnMessage
public String handleMessage(String message,Session session){
chatService.saveSessionAdminJava(session.getId())
}
#OnError
public void handleError(Throwable t){
println "error ~"
}
private void sendMessageToAll(String message){
println "session.size() = "+sessions.size()
for(Session s : sessions){
try {
s.getBasicRemote().sendText(message);
println "sent to session = "+s.getId()
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
`
I tried to use this code for calling a method from service:
try {
def ctx = Holders.applicationContext
chatService = ctx.chatService
} catch (Exception e) {
println "e = " + e
}
This is my service:
package com.akiong.services
import com.akiong.maintenance.Chat
class ChatService {
def serviceMethod() {
}
def saveSessionAdminJava(def sessionJava) {
println "jaln!!!"
def chatInstance = Chat.findByIsAdmin("1")
chatInstance.sessionJava = sessionJava
chatInstance.save(failOnError: true)
}
}
But after I tried to run this code, I'm getting this error:
Error : groovy.lang.MissingPropertyException: No such property: chatService for
class: com.akiong.ServerEndPointDemo
Anyone know how to call a method from service to file in src/groovy?
So here is the problem. The code you written is correct for injecting service:
try {
def ctx = Holders.applicationContext
chatService = ctx.chatService
} catch (Exception e) {
println "e = "+e
}
But the chatService is not defined anywhere in your class. So even if your handleOpen method is invoked there must be MissingPropertyException being thrown but since you have handled the top level Exception class (which should never be encouraged) that exception from your handleOpen method got suppressed.
Now, later in your handleMessage method, the same problem is occurring again of chatService being undefined and hence you are getting the exception you posted in your question.
So, you know the answer now :-) Simply define the chatService in your ServerEndPointDemo class.
Update:
public class ServerEndPointDemo implements ServletContextListener {
private static HashMap<String, String> usersMap = new HashMap<String, String>();
private static final Set<ServerEndPointDemo> connections = new CopyOnWriteArraySet<>();
private String username
private Session session
def chartService // Initialize here
// rest of your code
}
import org.apache.commons.logging.LogFactory;
import org.codehaus.groovy.grails.commons.ApplicationHolder as AH
class MyClass{
private static final log = LogFactory.getLog(this)
def ctx = AH.application.mainContext
def authService=ctx.authService
def method(){
log.debug "into MyClass method"
}
}

How to get name of currently running test in spock?

In JUnit 3, I could get the name of the currently running test like this:
public class MyTest extends TestCase {
public void testSomething() {
assertThat(getName(), is("testSomething"));
}
}
How do I do this in spock? I would like to use the test name as a key in a shared resource so that tests don't interfere with each other.
One solution is to leverage JUnit's TestName rule:
import org.junit.Rule
import org.junit.rules.TestName
class MySpec extends Specification {
#Rule TestName name = new TestName()
def "some test"() {
expect: name.methodName == "some test"
}
}
This requires JUnit 4.7 or higher.
For spock 1.0-groovy-2.4 you can try :
def "Simple test"() {
expect:
specificationContext.currentIteration.name == "Simple test"
}

Resources