How to load multiple contexts using jUnit and Spring - java

I have a junit test class with following annotations :
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("classpath:custom-context.xml")
There exists a class in another context that is required in my test that is autowired so I require this context to be loaded. How can this be implemented ?
I've tried :
#ContextConfiguration("classpath:custom-context.xml , classpath:custom-context2.xml")
But this does now work as it does not seem to load multiple contexts using the , delimiter.

Also can use widcard like this:
#ContextConfiguration({"classpath:custom-*.xml" })

Use an array of strings, like :
#ContextConfiguration(locations={ "classpath:custom-context.xml" , "classpath:custom-context2.xml" })
from spring api doc

Related

How to use "declare" instruction within Spring AspectJ?

I have a bunch of classes inside a Spring 4.2 project.
I'd like to have all of them annotated with #Xyz annotation. According to AspectJ documentation it could be done by
declare #type : x.y.z.* : #Xyz;
instruction.
But I have no clue where to place it.
I did some testing on my side and after some struggling, I looked for the concrete implementation. Sadly, #DeclareAnnotation exists but is not implemented.
We can see it here.
https://github.com/eclipse/org.aspectj/blob/V1_8_9/docs/adk15ProgGuideDB/ataspectj.xml#L1017
I thought it would be implemented sinced the annotation appeared in version 1.5.3. My bad.
Original answer (not working, AspectJ v1.8.9).
First you need to enable AspectJ in your configuration. For example, Java configuration :
#Configuration
#EnableAspectJAutoProxy
public class AopConfiguration {}
Then you create a new aspect with the #DeclareAnnotation annotation :
#Aspect
public class XyzAspect {
#DeclareAnnotation("x.y.z.*")
#Xyz class XyzClass {}
#DeclareAnnotation("x.y.z.MyClass.*(..)")
#Xyz void xyzMethod() {}
}

How to load a value from . properties file in Cucumber-jvm step class

I have written a cucumber integration tests and it is running ok.
And then i wanted some class variables from the step.java to get their values from .properties values
public class cucumberStepClass {
#Value("${value.from.propertiesfile}")
private String variable
//rest of integration test
}
Does anyone know how can i inject those values so my test can use them?
Have you enabled integration with spring dependency injection? You need to add the cucumber-spring dependency for that. See https://docs.cucumber.io/cucumber/state/#spring
To add my two cents to the first answer: remember to annotate the class with #SpringBootTest and #TestPropertySource("classpath:test.properties"). And the properties file should be .properties extension or .xml. .yml cannot be loaded.

How to use domain class methods on Utils or src/groovy?

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")

How to scan multiple paths using the #ComponentScan annotation?

I'm using Spring 3.1 and bootstrapping an application using the #Configuration and #ComponentScan attributes.
The actual start is done with
new AnnotationConfigApplicationContext(MyRootConfigurationClass.class);
This Configuration class is annotated with
#Configuration
#ComponentScan("com.my.package")
public class MyRootConfigurationClass
and this works fine. However I'd like to be more specific about the packages I scan so I tried.
#Configuration
#ComponentScan("com.my.package.first,com.my.package.second")
public class MyRootConfigurationClass
However this fails with errors telling me it can't find components specified using the #Component annotation.
What is the correct way to do what I'm after?
Thanks
#ComponentScan uses string array, like this:
#ComponentScan({"com.my.package.first","com.my.package.second"})
When you provide multiple package names in only one string, Spring interprets this as one package name, and thus can't find it.
There is another type-safe alternative to specifying a base-package location as a String. See the API here, but I've also illustrated below:
#ComponentScan(basePackageClasses = {ExampleController.class, ExampleModel.class, ExmapleView.class})
Using the basePackageClasses specifier with your class references will tell Spring to scan those packages (just like the mentioned alternatives), but this method is both type-safe and adds IDE support for future refactoring -- a huge plus in my book.
Reading from the API, Spring suggests creating a no-op marker class or interface in each package you wish to scan that serves no other purpose than to be used as a reference for/by this attribute.
IMO, I don't like the marker-classes (but then again, they are pretty much just like the package-info classes) but the type safety, IDE support, and drastically reducing the number of base packages needed to include for this scan is, with out a doubt, a far better option.
Provide your package name separately, it requires a String[] for package names.
Instead of this:
#ComponentScan("com.my.package.first,com.my.package.second")
Use this:
#ComponentScan({"com.my.package.first","com.my.package.second"})
Another way of doing this is using the basePackages field; which is a field inside ComponentScan annotation.
#ComponentScan(basePackages={"com.firstpackage","com.secondpackage"})
If you look into the ComponentScan annotation .class from the jar file you will see a basePackages field that takes in an array of Strings
public #interface ComponentScan {
String[] basePackages() default {};
}
Or you can mention the classes explicitly. Which takes in array of classes
Class<?>[] basePackageClasses
You use ComponentScan to scan multiple packages using
#ComponentScan({"com.my.package.first","com.my.package.second"})
You can also use #ComponentScans annotation:
#ComponentScans(value = { #ComponentScan("com.my.package.first"),
#ComponentScan("com.my.package.second") })
I use:
#ComponentScan(basePackages = {"com.package1","com.package2","com.package3", "com.packagen"})
make sure you have added this dependency in your pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Use
#ComponentScan(basePackages = {"package1", "package2"})
define it at top before class.
Edit: the brackets must be around all the base packages, not a pair of brackets per package

Is it possible to exclude multiple categories in JUnit 4?

I would like to do something like:
#RunWith(Categories.class)
#Categories.IncludeCategory(Small.class)
#Categories.ExcludeCategory({Manual.class, NonFunctional.class})
#Suite.SuiteClasses(AllTests.class)
public class SmallTests {
}
but ExcludeCategories accepts only one class, not an array of classes.
This will be supported in JUnit 4.12 version, see https://github.com/junit-team/junit/blob/master/src/main/java/org/junit/experimental/categories/Categories.java
It looks like runtime-suite may provide another workaround/solution.
There's a JUnit 4 feature request for this:
https://github.com/junit-team/junit/issues/146
This link also suggests a workaround:
There is a not-so-beatiful workaround. You can get multiple includes or excludes
if you create an inheritance hierarchy of suites and exclude one category on
each level.

Categories

Resources