How to inject log property in Grails 3 unit tests? - unit-testing

I'm trying to upgrade my Grails 2 project to Grails 3. I'm having problems with running tests for code blocks that use logging as it throws NoSuchPropertyException for log property. This was no problem with Grails 2 as the property is automatically injected. How do I get this working in Grails 3? I'm using 3.0.2.

Add the #groovy.util.logging.Slf4j class annotation to your Spec and log will be injected.

I've been doing this in my Groovy classes, I don't know whether this will work for your tests:
import org.slf4j.Logger
import org.slf4j.LoggerFactory
// within my class that I want to call log on
private static final Logger log = LoggerFactory.getLogger(MyClass.class)
// now you can call log from within a method
log.info("Log foo")

Related

Unit Test fails with GrailsConfigurationException - cannot find responsible line of code

I am writing unit tests for my Grails 3.0.3 application with standard spock framework. Everything as scaffolded by
grails create-app
I created my unit test with
grails create-unit-test
Added manually #TestFor annotation and test logics. I get
mypackage.MyClassSpec > test myMethod method FAILED
org.grails.core.exceptions.GrailsConfigurationException
GIST of My test class (generalized and simplified)
There is no line number in stacktrace after running
grails test-app --stacktrace
How can I find out what is causing this exception?
The TestFor annotation is used to test Grails artefacts (yes, that's how it's spelled in the source code).
The TestFor annotation defines the class under test and will
automatically create a field for the type of class under test. For
example in the above case a "controller" field will be present,
however if TestFor was defined for a service a "service" field would
be created and so on.
The class you were testing is a plain Groovy class, not a Grails controller, service, etc. So, BAM! You got an awkward exception.

Zend Framework 2 unit testing using CodeCeption

We are currently using CodeCeption to do some acceptance testing, but I would like to also add unit testing to the current setup.
Has anyone done Unit testing in Zend Framework 2 project using CodeCeption? And if so, how did you set up the environment?
Found this in codeception docs: http://codeception.com/docs/modules/ZF2
There is an example in this github project: https://github.com/Danielss89/zf2-codeception
I solved this problem by using PHPUnit. I followed the Zend PHPUnit guide, http://framework.zend.com/manual/current/en/tutorials/unittesting.html, which only got me so far. But, I was able to bootstrap Zend using a phpunit.xml file and pointing that to _bootstrap.php. Codeception is also able to bootstrap my tests using the _bootstrap.php file. So, now I can run my tests using both:
phpunit --bootstrap tests/unit/_bootstrap.php
and
php vendor/bin/codecept run unit
I was surprised to see how few examples there are for this. I was writing tests for a job queue client. Here is a bit of my test:
protected function setUp()
{
$this->serviceManager = new ServiceManager(new ServiceManagerConfig());
$config = Bootstrap::getConfig();
$this->serviceManager->setService('ApplicationConfig', $config);
$this->serviceManager->get('ModuleManager')->loadModules();
$this->client = $this->serviceManager->get('jobclient');
$this->client->addServers(array(array('ip' => '127.0.0.1', 'port' => '666')));
}
public function testServiceCreateSuccess() {
$this->client->setQueue($this->testData['queue']);
$this->assertEquals($this->client->getQueue(), $this->testData['queue'], 'We get the expected queue');
}
I mocked the job client and had a local config. My _bootstrap.php file looks basically the same as the Zend example except that I am using factories defined in the service config to manage some objects. So, I performed the "setService" method in the test setup rather then in the bootsrap init.

Http.Context with FakeApplication and illusive mock method

In my tests I create a fake application per test method:
#Before
public void startFakeApplication() {
this.fakeApplication = fakeApplication();
start(this.fakeApplication);
}
#After
public void killFakeApplication() {
stop(this.fakeApplication);
this.fakeApplication = null;
}
Some of the tests use functionality that checks if the request is secure or not:
public boolean isHttps() {
Http.Request req = Controller.request();
return req.getHeader("x-forwarded-proto") != null
&& req.getHeader("x-forwarded-proto").contains("https");
}
That fails saying:
There is no HTTP Context available from here
Which is pretty strange, since it's running on a fake app, why can't it know that and create a fake request?
Oh well, I found this: Play framework 2.2.1: Create Http.Context for tests which introduced me to the mocking approach, so I was eager to give it a go and try to mock the Http.Context in the same way, the problem is that I can't seem to find the mock method...
In that thread he's using import static org.mockito.Mockito.* (which is where I assume the mock method is located) but I don't have that package, org.mockito only has one sub package named internal and I can't find any mock method there.
In the official documentation of Play! the only place talking about it is the Scala Test section and they use: import org.specs2.mock._ but there too I wasn't able to locate this mock method.
I'm using Play 2.2.2 (java).
Any ideas? Thanks.
I solved the same problem adding to my build.sbt the library dependency of Mockito:
libraryDependencies += "org.mockito" % "mockito-core" % "1.10.19"
Then I run play compile and play eclipse and magically the mockito library became available after refreshing the whole project in Eclipse.
And yes, mock() is a method of org.mockito.Mockito.
I had the same problem of Play not locating the mock function, and eventually realised that I hadn't extended my test class with Mockito;
import org.specs2.mock._
class TestClass extends Specification with Mockito
Just thought I'd add this as it has taken me ages to resolve and the above solution didn't work for me ......may save someone some time :)

How to mock g.message while writing unit test for grails controller

I am using grails version 1.3.7. In my application in controller, I am making use of messages.properties and fetching the value of the property as
g.message(code:messageKey, args:msgParamsArr)
But when I started writing unit tests for the action in the controller, it gave me errors.
Please can you help me out to understand how to mock g.message exactly so that the existing code will fetch the message properties from messages.properties only.
You can mock it with:
controller.metaClass.message = { message ->
message.code
}
You can include message.args too if you want to just validate the arguments with .contains().
This works like a champ in Grails 2.4.5:
controller.metaClass.message = { Map attrs -> attrs.toString() }

Grails Unit Test Buggy Dynamic Finder

I am in the process of writing unit tests for a service class. This service class calls MyDomain.findAllByIdNotInList. The issue I am facing is that grails does not recognize NotInList as a dynamic finder for a mocked domain. I tried Metaclass-ing this functionality out, but was having issues with it.
Any creative ways for bypassing this short of turning the Unit Test into an Integration test? I would like to avoid this for multiple reasons (time to run, Only our Unit tests run at build time, etc)
Also, it is possible my metaclassing is written poorly:
MyDomain.metaClass.findAllByIdNotInList = {ArrayList list ->
return []
}
Edit: Using grails 1.3.7.
also tried
MyDomain.metaClass.findAllByIdNotInList = {deflist ->
return []
}
Bug report here:
http://jira.grails.org/browse/GRAILS-8593
#Sagar V's comment is correct you should be able to utilize all dynamic finders when a Domain is properly mocked. If you're using a version of Grails before 2.0 you'd have to extend GrailsUnitTestCase and call MockDomain(MyDomain) before attempting to invoke the dynamic finders. As an FYI your metaClassing is not written properly (in my opinion you should use the mocking framework to get your test working I'm providing the correct syntax so you can use it properly in the future).
MyDomain.metaClass.'static'.findAllByIdNotInList = {defList ->
[]
}
When the method that you're overriding is static you need to add the .'static'. inbetween the metaClass and the method name.