Grails Unit testing GORM global constraints - unit-testing

I have an issue where the global constraints setup in the Config are not working when running unit tests.
This is in my Config.groovy:
grails.gorm.default.constraints={
'*'(nullable:true, bindable:true)
}
in my test I have tried this:
static doWithConfig(c){
c.grails.gorm.default.constraints={
'*'(nullable:true, bindable:true)
}
and also in the setupSpec():
grailsApplication.config.grails.gorm.default.constraints={
'*'(nullable:true, bindable:true)
}
All I'm doing in my test is trying to create a domain object from a json string. Is there anything special that I should be doing to get this to work in the Unit test? This is also using the Gorm-MongoDb plugin.

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.

Grails unit or integration tests?

I don't know whether to use unit or integration tests for what I am wanting to test in my Grails 2.2.3 application. I want to run some tests against like this:
#TestFor(Student)
#Mock(Student)
class StudentTests {
void testFoundStudent() {
def s = Student.findById(myId)
assert s != null
assert s.firstName = 'Grant'
assert s.lastName = 'McConnaughey'
}
}
This is going to require the use of our test database, so would that make it an integration test? When I run this code as a unit test it fails at assert s != null. Which means it isn't using our database, because it SHOULD find a student with that ID.
In Grails unit test you can test domain class interactions using Gorm and behind the scene Grails will use in-memory database(an implementation of a ConcurrentHashMap) to mimic this behavior here. So yes you get null because that student does not exist in in-memory database and you need to insert that data first.
Student.findOrSaveWhere (firstName: 'Grant',lastName : 'McConnaughey')
In your example, if the intention is to test the existence of that data you need to use integration test and connect it to your database using datasource.groovy , which is really not a good idea unless you have a good reason to test your data.
If you are trying to test def s = Student.findById(myId) again that is not adding any value as that is Grails dynamic finder and you probably need to trust the framework you are using.
However, in general
Unit tests are typically run without the presence of physical
resources that involve I/O such databases, socket connections or
files link
I hope this helps

Using IOC To Configure Unit and Integration Tests

I have a unit test project which uses Ninject to mock the database repositories. I would like to use these same tests as integration tests and use Ninject to bind my real database repositories back into their respective implementations so as to test/stress the application into the DB.
Is there a way to do this with Visual Studio 2012 or is there another test framework, other than MSTest, which allows for this type of configuration?
I would really hate to rewrite/copy these unit tests into an integration test project but I suspect I could copy the files in as links and have a single test file compiled into two projects (Unit and Integration).
Thanks
Todd
Your requirements sound really odd to me. The difference between a unit test and an integration test is much bigger than just connecting to a database or not. An integration test either has a much bigger scope, or tests if components communicate correctly. When you write a unit test, the scope of such a unit is normally small (one class/component with all dependencies mocked out), which means there is no need for using a DI container.
Let me put it differently. When the tests are exactly the same, why are you interested to do the same test with and without the database. Just leave the database in and just test that. Besides these tests, you can add 'real' unit tests, that have a much smaller scope.
With Nunit you can do this with TestCase,
say you need to use the unit and unit/integration test using CustomerRepository and OrderRepository,
[TestFixture]
public class TestCustomerRepository
{
IKernel _unit;
Ikernel _integration;
[SetUp]
public void Setup()
{
//setup both kernels
}
[TestCase("Unit")]
[TestCase("Integration")]
public void DoTest(String type)
{
var custRepo = GetRepo<ICustomerRepository>(type);
var orderRepo = GetRepo<IOrderRepository>(type);
//do the test here
}
protected T GetRepo<T>(String type)
{
if (type.Equals("Unit"))
{
return _unit.Get<T>();
}
return _integration.Get<T>();
}
}
This is the basic idea.

call to .save() on domain class fails with no signature of method .save() in unit test

I'm using Grails 1.3.2 in NetBeans. I have a very simple unit test that fails with this error:
No signature of method: com.maxrecall.maxrequire.domain.Release.save()
is applicable for argument types: (java.util.LinkedHashMap) values:
[[flush:true]] Possible solutions: wait(), any(), wait(long),
isCase(java.lang.Object), use([Ljava.lang.Object;), sleep(long)
The relevant code is:
Release rel = new Release()
...
rel.save(flush:true)
The same code works in BootStrap.groovy. I have tried various variations on .save() (.Save with and without parameters.
It's a unit test, so there's no Spring, Hibernate, etc. You have to mock the behavior you want.
If you're testing persistence, you need to convert the test to an integration test, since testing persistence with unit tests just tests the mocking framework. An integration test uses at a minimum an in-memory database, although you can easily switch that for a test instance of MySQL/Oracle/etc.
If you're testing controllers or other users of your domain classes and just want them to work so you can focus on testing the current class, use mockDomain and the other mock methods available in the Grails unit test base classes.
This is all described in detail in the documentation - see http://grails.org/doc/latest/guide/9.%20Testing.html
There's no grails magic around in a unit test (it's there in an integration test). See "Understanding mockDomain()" here or read the Grails docs.

Grails. mocked data from a unit test is available in an integration test

Im having a failed integration test because of test pollution (tests pass or fail depending on which order they are run in).
What baffles me a bit however is that it seems that a unit test where i have mocked some data with mockDomain(Media.class,[new Movie(...)]) is still present and available in other tests, even integration tests.
Is this the expected behaviour? why doesn't the test framework clean up after itself for each test?
EDIT
Really strange, the documentation states that:
Integration tests differ from unit tests in that you have full access to the Grails environment within the test. Grails will use an in-memory HSQLDB database for integration tests and clear out all the data from the database in between each test.
However in my integration test i have the following code
protected void setUp() {
super.setUp()
assertEquals("TEST POLLUTION!",0,Movie.count())
...
}
Which gives me the output:
TEST POLLUTION! expected:<0> but was:<1>
Meaning that there is data present when there shouldn't be!
Looking at the data that is present int he Movie.list() i find that the data corresponds to data set in a previous test (unit test)
protected void setUp() {
super.setUp()
//mock the superclass and subclasses as instances
mockDomain(Media.class,[
new Movie(id:1,name:'testMovie')
])
...
}
Any idea's of why im experiencing these issues?
It's also possible that the pollution is in the test database. Check the DataSources.groovy to see what is being used for the test environment. If you have it set to use a database where
dbCreate is set to something other than "create-drop", any previous contents of the database could also be showing up.
If this is the case, the pollution has come from an entirely difference source. Instead of coming from the unit tests, it has actually come from the database, but when switching to run the integration tests you get connected to a real database with all the data it contains.
We experienced this problem, in that our test enviroment was set to have dbCreate as "update". Quite why this was set for integration tests puzzled me, so I switched to use dbCreate as "create-drop" and make sure that when running test suites we started with a clean database.