I am working with grails application. I want to perform methods like get(),save(),delete(),findBy() etc and associated with domains of grails application. When I execute Domain.get() method inside Utils or src/groovy package I get following error.
Caught: java.lang.IllegalStateException: Method on class [Domain Class] was used outside of a Grails application. If running in the context of a test using the mocking API or bootstrap Grails correctly.
java.lang.IllegalStateException: Method on class [Domain Class] was used outside of a Grails application. If running in the context of a test using the mocking API or bootstrap Grails correctly.
Any one help me how can I use domain class method inside Utils or src/groovy classes?
This error is caused by interacting with GORM entities that have not been properly registered with GORM. The error doesn't have anything to do with where the interaction is initiated from (src/groovy, grails-app/services/, etc...).
Not always, but most often this error occurs in a testing environment where the entity type has not been registered with GORM.
See the project at https://github.com/jeffbrown/illegalaccessgorm. That project contains the following.
A domain class:
// grails-app/domain/demo/Person.groovy
package demo
class Person {
String name
}
A service:
// grails-app/services/demo/HelperService.groovy
package demo
class HelperService {
int getNumberOfPeople() {
Person.count()
}
}
A utility class:
// src/groovy/demo/SomeHelper.groovy
package demo
class SomeHelper {
int getNumberOfPeople() {
Person.count()
}
}
A unit test for the service:
// test/unit/demo/HelperServiceSpec.grovy
package demo
import grails.test.mixin.TestFor
import spock.lang.Specification
#TestFor(HelperService)
#Mock(Person)
class HelperServiceSpec extends Specification {
void "test gorm method"() {
expect:
service.numberOfPeople == 0
}
}
A unit test for the utility class:
// test/unit/demo/SomeHelperSpec.groovy
package demo
import spock.lang.Specification
#Mock(Person)
class SomeHelperSpec extends Specification {
void "test gorm method"() {
given:
def helper = new SomeHelper()
expect:
helper.numberOfPeople == 0
}
}
Both of those tests pass. If you remove the #Mock(Person) from either of them, the test will fail with the following:
java.lang.IllegalStateException: Method on class [demo.Person] was used outside of a Grails application. If running in the context of a test using the mocking API or bootstrap Grails correctly.
If the problem is happening in some context other than a test, knowing more about the context would be helpful. Other likely suspects are Java entities that are not being initialized properly for some reason and in some cases domain classes brought in from plugins can be problematic.
Also, knowing what version of Grails you are using may be relevant.
I hope that all makes sense.
You shouldn't use domain classes inside src/groovy or inside utils. You should use services for it. Check out best practises for Grails architecture:
Domain
Favor placing model domain specific logic in its own domain. Anything that applies to a single domain with few dependencies should go in its domain class. But keep it restricted to the logic specific to that domain only - more complex business logic that deals with a group of domains belongs to a service.
To reuse common partial queries or decompose the complex logic, use named queries and chain them together as required, just like one commonly chains jQuery function calls.
Don't mix any other common utility classes or value objects in the domain folder, rather they can go in src/groovy. If these classes need to support validation, one can annotate them with #Validateable.
If you still want to do it, check this FAQ:
import org.codehaus.groovy.grails.commons.ApplicationHolder
//…
def book = ApplicationHolder.application.getClassForName("library.Book").findByTitle("Groovy in Action")
Related
I have an application I want to test:
import foo.ExtClass;
public class App {
public static void main(String[] args) {
ExtClass ext = new ExtClass();
...
}
}
I want to write a unit test for this application, however I do not want to use the foo.ExtClass, but use another mock implementation for the class.
Normally I would use a factory to instantiate the class according to some configuration that can be controlled in the unit test.
However, in this case, I cannot modify the tested app.
I was thinking in the direction of writing a custom class loader to load the mock class instead of the real class - not sure if this is possible without any modification to the tested app, and how.
As an option you can use custom classloader, which will substite your class with a testing one. So basically instead of loading ExtClass from your app package, your classloader will load the same class from your testing package with the mock implementation.
Here is an example:
How to replace classes in a running application in java ?
Also there is very usefull tutorial: https://zeroturnaround.com/rebellabs/reloading-objects-classes-classloaders/
The approach I finally used:
Created a separate project with my mock implementation of foo.ExtClass,
and the unit tests.
This way the mock implementation appeared in the classpath before the real implementation, and the original (tested) project remained untouched.
I am running into trouble with JUnit 5 (5.0 or 5.1) and custom extension.
We are using service loader to load all implementations which then modify how our extension is bootstrapped. These implementations can be loaded just once, so I was thinking of using ExtensionContext.Store and placing it there. Every subsequent test instance would then just load it from Store instead of via service loader.
Now, I am even aware of the hierarchical context structure and I know that there is some "root" context which you can get through ExtensionContext.getRoot(). But this "root" context (instance of JupiterEngineExtensionContext) isn't really root - there is different one for every test instance.
Say you have FooTest and BarTest, then printing out getRoot() for each of them yields:
org.junit.jupiter.engine.descriptor.JupiterEngineExtensionContext#1f9e9475
org.junit.jupiter.engine.descriptor.JupiterEngineExtensionContext#6c3708b3
And hence trying to retrieve previously stored information from Store fails.
Is having this limitation intended? It makes the borderline between ClassExtensionContext and JupiterEngineExtensionContext pretty blurred.
Is there another way to globally store some information via extension?
Here is a (very) simplified version of how I tried working with the store (cutting out all other information basically). I also added some System.out.print() calls to underline what I am seeing. Executing this extension on two test classes results in what I described above:
public class MyExtension implements BeforeAllCallback {
#Override
public void beforeAll(ExtensionContext context) throws Exception {
System.out.println(context.getRoot());
if (context.getRoot().getStore(Namespace.create(MyExtension.class)).get("someIdentifier", String.class) == null) {
context.getRoot().getStore(Namespace.create(MyExtension.class)).put("someIdentifier", "SomeFooString");
} else {
// this is never executed
System.out.println("Found it, no need to store anything again!");
}
}
}
EDIT: Here is a minimal project on GH(link), run by mvn clean install, which displays the behaviour I see.
I just copied your MyExtension verbatim (i.e., with zero changes) and ran both FooTest and BarTest.
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
#ExtendWith(MyExtension.class)
class FooTest {
#Test
void test() {
}
}
and
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
#ExtendWith(MyExtension.class)
class BarTest {
#Test
void test() {
}
}
And the result is:
org.junit.jupiter.engine.descriptor.JupiterEngineExtensionContext#2280cdac
org.junit.jupiter.engine.descriptor.JupiterEngineExtensionContext#2280cdac
Found it, no need to store anything again!
Thus, getRoot() works as documented.
The only explanation for why you see two different roots is that you must be executing the tests in different processes.
Please keep in mind that the root ExtensionContext instance is bound to the current execution of your test suite.
So if you run FooTest and BarTest one after the other in an IDE, that will actually result in two "test suites" with different roots. The same is true if you configure your build tool to fork between test classes.
Whereas, if you execute both test classes together in a single "test suite" (e.g., by telling your IDE to run all tests in the same package or same source tree) you will then see that there is one root like in the output I provided above.
Note, however, that there was an issue with the junit-platform-surefire-provider prior to version 1.0.3, whereby the provider launched the JUnit Platform for each test class. This would give the appearance of forking even though Surefire did not actually start a new JVM process. For details, see https://github.com/junit-team/junit5/pull/1137.
I've got a utility class that I've created:
package com.g2.quizification.utils;
import com.g2.quizification.domain.Question;
public class ParsingUtils {
public static Question parse(String raw) {
Question question = new Question();
//TODO: parse some stuff
return question;
}
}
...that lives here:
I've also followed the tutorials and created a testing app, that looks like this:
And here's my test code, just waiting for some good 'ole TDD:
package com.g2.quizification.utils.test;
import com.g2.quizification.domain.Question;
import com.g2.quizification.utils.ParsingUtils;
public class ParsingUtilsTest {
public void testParse() {
String raw = "Q:Question? A:Answer.";
Question question = ParsingUtils.parse(raw);
//assertEquals("Question?", question.getQuestion());
//assertEquals("Answer.", question.getAnswer());
}
}
The test class is obviously missing the extension, but all the examples seem to only show extending something like ActivityUnitTestCase. I'm not testing an activity; I just want to test a static method in a utility class. Is that possible?
It seems like creating a utility test class should be simple, but I'm not sure what the next step is and/or what I'm missing.
The best approach for test project is to add the test project so that its root directory tests/ is at the same level as the src/ directory of the main application's project. If you are using junit4 and eclipse, you can just right-click on the util class you want to test and choose New -> JUnit Test Case.
Basically I would expect a new test class named ParsingUtilTest under the source folder tests/ and within the package com.g2.quizification.utils.test. The test class should extend TestCase and each method you want to test in that util class should have a new method in the test class with the name preceded with "test". I mean to say, suppose you have a method name in ParsingUtils called parseXml. The test method name in ParsingUtilsTest (which Extend 'TestCase') should be named testParseXml
The test class is obviously missing the extension, but all the examples seem to only show extending something like ActivityUnitTestCase. I'm not testing an activity; I just want to test a static method in a utility class. Is that possible?
Yes, as long as the class your are testing has nothing to do with android apis. And if you do need to test code with android api dependencies, for example, testing a view or an activity, you might want to have a try with robolectric. It's faster than the ones that extend ActivityUnitTestCase.
I have been playing with robolectric a lot (to do TDD on android), and so far, I prefer version 1.1 or 1.2 to 2.x, more stable and run fast.
Besides the tools mentioned above, there are many practices for writing good test cases, naming conventions, code refactoring and such.
It seems like creating a utility test class should be simple, but I'm not sure what the next step is and/or what I'm missing.
Its good to begin with small steps, xUnit Test Patterns: Refactoring Test Code and Extreme Programming Explained are some good books for your reference.
In my current project I would like to store some configuration data in a package annotation and to access it by some CDI producers. If the annotation is not found in the current package the producers will search for it upward in the package hierarchy.
So far so good. Unfortunately it seems so that I can access an existing package via Package.getPackage("my.package") only after the first access to one of its classes or interfaces.
The following example illustrates this behaviour:
Class in package a.b
package a.b;
public class ClassInMitte {
}
Example programm to access the package oben.mitte
package other;
public class Refl {
public static void main(String[] args)
{
Package viaName = Package.getPackage("a.b");
System.out.println(viaName.getName());
System.out.println(viaName.hashCode());
}
}
Running Refl results in a NullPointerException. But if I add new ClassInMitte() as first statement I can access the package information. Somehow I must access the content of a package before I can access the package information itself. This makes sense since otherwise the classloaders must scan the whole classpath while starting.
But netherless is there an easy way to access package information without accessing the content of the package before? I know I could use frameworks like reflections but a 'lightweight' solution would be my prefered solution.
Package.getPackage only returns packages that are already known to the current class loader, and the only way to do that is by loading a class from that package. It's basically a wrapper for ClassLoader.getPackage.
In my grails application I have Java classes (src/java). And I want to have access to my domain classes and use GORM features(like get(), findBy..., save(), delete() and etc.) directly from my Java classes. I know, I can do this by Spring IoC: for example, I can add grails service to my Java class:
public class SimpleJavaClass{
//...
#Autowired
private ExampleService exampleService;
//...
}
And wireup each instance of this class by Spring:
//...
GrailsApplication grailsApplication
//...
def simpleAction(){
def instance = new SimpleJavaClass()
grailsApplication.mainContext.autowireCapableBeanFactory.autowireBean(instance)
}
But may be there is more appropriate way to do same?
Using Grails 2.0, the only current way is to package your domain classes into a binary plugin (see http://grails.org/doc/2.0.x/guide/single.html#binaryPlugins)
You then can depend on this binary plugin and because it is precompiled the Java code will see many of the GORM methods which are wired into the byte code