So I have a grails domain class:
class Message
{
Inbox inbox
Boolean hasBeenLogicallyDeletedByRecipient
...
static belongsTo = [
inbox:Inbox,
...
]
static constraints = {
hasBeenLogicallyDeletedByRecipient(nullable:false)
...
}
}
I would like to use a dynamic finder as follows:
def messages = Message.findAllByInboxAndHasBeenLogicallyDeletedByRecipient(
inbox, false, [order:'desc',sort:'dateCreated'])
This works fine running a unit test case in STS 2.6.0.M1 against grails 1.2.1;
Spinning up the web app, it fails because of the By in hasBeenLogicallyDeletedByRecipient (I'm guessing it has confused the dynamic finder parsing when building up the query).
I can use a criteria builder which works in the app:
def messages = Message.withCriteria {
and {
eq('inbox', inbox)
eq('hasBeenLogicallyDeletedByRecipient', false)
}
order('dateCreated', 'desc')
}
But since withCriteria is not mocked, it doesn't immediately work in unit tests, so I could add the following to the unit test:
Message.metaClass.static.withCriteria = { Closure c ->
...
}
Is the criteria/unit test mocking the best/accepted approach? I don't feel completely comfortable with mocking this, as it sidesteps testing the criteria closure.
Ideally, I'd rather use the dynamic finder - is there a succinct way to make it work as is?
If there is no way around it, I suppose the field name could be changed (there is a reason why I don't want to do this, but this is irrelevant to the question)...
UPDATE:
Here's the stacktrace when I try to use findAllByInboxAndHasBeenLogicallyDeletedByRecipient() inside the app - notice how it appears to get the last By and treat everything else between it and findAll as a property. i grazed on http://grails.org/OperatorNamesInDynamicMethods but it doesn't mention anything about By being verboten.
org.codehaus.groovy.grails.exceptions.InvalidPropertyException: No property found for name [byInboxAndHasBeenLogicallyDeleted] for class [class xxx.Message]
at xxx.messages.yyyController$_closure3.doCall(xxx.messages.yyyController:53)
at xxx.messages.yyyController$_closure3.doCall(xxx.messages.yyyController)
at java.lang.Thread.run(Thread.java:662)
Testing the database querying is really an Integration test, not a unit test. Is your test in /test/unit or /test/integration ? - I'd expect the 'withCriteria' to be fully functional in the integration tests, but not in unit tests.
From the grails docs ( http://grails.org/doc/latest/ ), section 9.1:
Unit testing are tests at the "unit"
level. In other words you are testing
individual methods or blocks of code
without considering for surrounding
infrastructure. In Grails you need to
be particularity aware of the
difference between unit and
integration tests because in unit
tests Grails does not inject any of
the dynamic methods present during
integration tests and at runtime.
Related
We want to introduce property-based testing into our Quarkus project, preferably with jqwik. We already got numerous test cases using junit jupiter. We also use CDI in out test cases.
Getting jqwik running in a small Quarkus example project went well, so I wanted to write some properties in out big project. jqwik is running, however, the #Property, #Example and #Provider methods do not have access to the injected bean (as in: the injected bean is Null, TreeRepository in the example below). Same for ArbitrarySupplier subclasses. If I replace the #Example with a #Test the referring test can access the bean and the test passes.
My first guess is that this has something to do with the jqwik lifecycle. I did not find enough information about how (and if?) jqwik integrates with injection.
How do I get this running?
In the example I expect treeRepository to be an instance of TreeRepository (the class is #ApplicationScoped). Instead it is null, except for in the method with the #Test annotation.
#QuarkusTest
class MyTestClass {
#Inject
TreeRepository treeRepository;
#Test
void testSimple() {
final Collection<Tree> trees = this.treeRepository.getTrees() // works
assertThat(trees).isNotEmpty();
}
#Example
void testSimple() {
final Collection<Tree> trees = this.treeRepository.getTrees() // does not work
assertThat(trees).isNotEmpty();
}
#Property
void treesHaveLeaves(#Forall("tree") Tree tree) { // does not work
assertThat(tree.getLeaves()).isNotEmpty();
}
Arbitrary<Tree> tree() {
final Collection<Tree> trees = this.treeRepository.getTrees(); // does not work
return Arbitraries.of(trees);
}
}
There is bad news and maybe a bit of good news.
The bad news: #QuarkusTest is specially made for use with JUnit Jupiter. Jupiter and jqwik are two different test engines for the JUnit Platform. The lifecycles of different engines do not compose, that's why treeRepository will not be injected automatically when you're executing jqwik properties or examples.
The good news is that it's probably not too difficult to create something like #JqwikQuarkusTest for your integration of jqwik and Quarkus.
If you want to do that yourself you can use jqwik's Spring support as an inspiration or template: https://github.com/jlink/jqwik-spring. Or you read up about jqwik's hooks here: https://jqwik.net/docs/current/user-guide.html#lifecycle-hooks and start from scratch.
If you don't feel up to the task yourself, you might want to think about paying someone to do it for you or your company. I'd be happy to help out.
I am building a Grails REST application and I have written my Functional Tests using Spock.
Note that these functional tests are for REST services only.
class LoginFunctionalSpec extends Specification {
def setUp() {
// here I want to access grailsApplication.config
}
}
I have already tried the following approaches:
Injecting grailsApplication (by defining as class level variable), but nothing get's injected.
Using ApplicationHolder.application.config but it has been deprecated and the suggested approach was the previous point.
Tried using plugin remote-control:1.4 but although grails console showed the plugin as installed I didn't find the class RemoteControl. Also I was never sure of this approach
I tried reading grails-app/conf/Config.groovy as a file (as explained here) but got a FileNotFoundException.
But none of them provide me grailsApplication.config inside my functional test.
Is there any way to achieve this ?
UPDATE
#dmahapatro
I am not using Geb because I am testing REST services and there is no browser automation required.
As I said in point#1 grails Application is not being auto-injected.
class LoginFunctionalSpec extends Specification {
def grailsApplication
def setUp() {
def port = grailsApplication.config.mongo.port //throws NPE
}
}
It throws a NPE saying that config property is being invoked on null object.
I think you do not need to inject anything explicitly. grailsApplication is available in the tests by default.
class LoginFunctionalSpec extends Specification {
def setUp() {
grailsApplication.config.blah //should work
}
}
Note-
Spock does not provide direct support for functional tests. You need to use Geb for proper functional tests.
Are you running your test in integration test phase or functional test phase?
You need to extend from IntegrationSpec to get autowiring in integraton test phase but you are talking about functional tests here... Because of grails running your tests in the same JVM as the application under tests you don't really need to use RemoteControl but I always do anyway in my functional tests as it seems much cleaner to me and is a really powerful technique if your tests and application under tests are not running in the same JVM.
I am dealing with a case where my tests pass or fail based on the order of declaration. This of-course points to not properly isolated tests. But I am stumped about how to go about finding the issue.
The thing is my junit tests derive from a class that is belongs to a testing framework built on junit and has some dependency injection container. The container gets reset for every test by the base class setup and so there are no lingering objects at least in the container since the container itself is new. So I am leaning toward the following scenario.
test1 indirectly causes some classA which sets up classA.somestaticMember to xyz value. test obj does not maintain any references to classA directly- but classA is still loaded by vm with a value xyz when test1 ends.
test2 access classA and trips up on somestaticmember having xyz value.
The problem is a) I dont know if this is indeed the case- how do I go about finding that ? I cannot seem to find a reference to a static var in the code...
b) is there a way to tell junit to dump all its loaded classes and do it afresh for every test method ?
You can declare a method with #Before, like
#Before public void init()
{
// set up stuff
}
and JUnit will run it before each test. You can use that to set up a "fixture" (a known set of fresh objects, data, etc that your tests will work with independently of each other).
There's also an #After, that you can use to do any cleanup required after each test. You don't normally need to do this, as Java will clean up any objects you used, but it could be useful for restoring outside objects (stuff you don't create and control) to a known state.
(Note, though: if you're relying on outside objects in order to do your tests, what you have isn't a unit test anymore. You can't really say whether a failure is due to your code or the outside object, and that's one of the purposes of unit tests.)
so I think I'm perhaps not fully understanding how you would use an IOC container for doing Integration tests.
Let's assume I have a couple of classes:
public class EmailComposer : IComposer
{
public EmailComposer(IEmailFormatter formatter)
{
...
}
...
public string Write(string message)
{
...
return _formatter.Format(message);
}
}
OK so for use during the real application (I'm using autofac here) I'd create a module and do something like:
protected override void Load(ContainerBuilder containerBuilder)
{
containerBuilder.RegisterType<HtmlEmailFormatter>().As<IEmailFormatter>();
}
Makes perfect sense and works great.
When it comes to Unit Tests I wouldn't use the IOC container at all and would just mock out the formatter when I'm doing my tests. Again works great.
OK now when it comes to my integration tests...
Ideally I'd be running the full stack during integration tests obviously, but let's pretend the HtmlEmailFormatter is some slow external WebService so I decide it's in my best interest to use a Test Double instead.
But... I don't want to use the Test Double on all of my integration tests, just a subset (a set of smoke-test style tests that are quick to run).
At this point I want to inject a mock version of the webservice, so that I can validate the correct methods were still called on it.
So, the real question is:
If I have a class with a constructor that takes in multiple parameters, how do I make one of the parameters resolve to a an instance of an object (i.e. the correctly setup Mock) but the rest get populated by autofac?
I would say you use the SetUp and TearDown (NUnit) or ClassInitialize and ClassCleanup (MSTest) for this. In initialize you register your temporary test class and in cleanup you restore to normal state.
Having the DI container specify all the dependencies for you has the benefit of getting an entire object graph of dependencies resolved. However if there's a single test in which you want to use a different implementation I would use a Mocking framework instead.
I'd like to test a "withCriteria" closure and am not sure how to go about it. I see how to mock out the withCriteria call, but not test the code within the closure. When running the test that executes the "withCriteria", I keep getting a MissingMethodException, even though the code runs fine under the normal flow of execution. Any ideas?
Thanks!
Steve
I wouldn't go that route. Instead I'd move the query into the domain class as a static finder method and test it directly in an integration test with real data. Then you can easily mock the helper method when it's called in a controller or service test.
class YourDomainClass {
...
static List<YourDomainClass> findFooBar() {
YourDomainClass.withCriteria {
...
}
}
}
Then in a unit test:
def results = [instance1, instance2, instance3]
YourDomainClass.metaClass.static.findFooBar = { -> results }
This way you test that the query works against the in-memory database in an integration test but it's easy to mock it in unit tests.
Further to Burt's answer, check out named queries as described here:
http://blog.springsource.com/2010/05/24/more-grails-1-3-features/
You can then mock the property/method access in your unit tests as described by Burt.
Since nobody mentioned the option to create a DSL to run other DSLs here's a full disclosure of this method. I use it quite often with very good results.
Groovy/Grails testing DSLs
There's no mock implementation for Hibernate criteria at the present time. You'll need to use integration tests. However, Burt's recommendation of making this a static finder method is a good one for code organization. You should also look at named queries, described at http://www.grails.org/1.2+Release+Notes, for a nice syntax for this.