everybody, I am a beginner in Spring and I am encountering some problems with #DeclareParents. I follow the instructions in Spring In Action but I fail to realize the introduction.
Here are my codes.
I first define Interface performance
public interface Performance {
void perform();
}
and then implement the interface.
#Component
public class OnePerformance implements Performance {
#Autowired
public OnePerformance(){
}
public void perform() {
System.out.println("The Band is performing....");
}
}
I want to introduce method void performEncore() into Performance.
So I define the Interface,
public interface Encoreable {
void performEncore();
}
implement it,
#Aspect
public class DefaultEncoreable implements Encoreable{
public void performEncore() {
System.out.println("performEncore");
}
}
and introduce it,
#Aspect
#Component
public class EncoreableIntroduction {
#DeclareParents(value="Performance+",
, defaultImpl=DefaultEncoreable.class)
public static Encoreable encoreable;
}
I use autoconfiguration,
#Configuration
#EnableAspectJAutoProxy
#ComponentScan
public class ConcertConfig {
}
However, when testing, I fail to introduce method void performEncore().
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes= ConcertConfig.class)
public class OnePerformanceTest {
#Autowired
private Performance performance;
#Test
public void perform() throws Exception {
performance.perform();
}}
And I also enabled AspectJ Support Plugins.
I have read the book and several blogs carefully but I still can not find the cause. So what may be the cause of this problem? Thanks in advance.
Thanks for M. Deinum, NewUser and Wim Deblauwe. With their help, I finally figured out the problem. The previous JUnit4 class is not correct.
The proper solution to solve this problem is to cast Performance into Encoreable, and then call the performEncore() method.
The code is as follow:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes= ConcertConfig.class)
public class OnePerformanceTest {
#Autowired
private Performance performance;
#Test
public void perform() throws Exception {
Encoreable encoreable = (Encoreable)(performance);
encoreable.performEncore();
}
}
Related
I've spent several days looking for a way to move one of my #BeforeClass methods to listener class I can reference in xml where I define content os test suite.
Problem I'm facing is that I'm using Spring for DI, and in #BeforeClass method I add some attributes to testng context, so I can use them in other places (other listeners).
I tried using onStart(final ITestContext context) from ITestListener. But that method seems to be invoked before spring manages to create beans, and I cannot perform my operations, because all my beans are nulls.
I tried using onBeforeClass(ITestClass testClass) from IClassListener. But that method only provides ITestClass, which does not give me access to context, so I can't set my attributes.
Now I'm experimenting with onConfigurationSuccess(final ITestResult itr) from IConfigurationListener, but that requires using if statement to run my code only if configuration method name is equal to springTestContextPrepareTestInstance.
Does anyone know a better way of doing this?
[EDIT] code sample
#Component
public class CleanupHelper {
private static SomeBean someBean;
#Autowired
public CleanupHelper(SomeBean someBean){
CleanupHelper.someBean = someBean;
}
public static Object getSomething(){
return someBean.getSomething();
}
}
public class ExcludedGroupsListener implements IConfigurationListener {
#Override
public void onConfigurationSuccess(final ITestResult itr) {
if (itr.getName().contains("springTestContextPrepareTestInstance")) {
var something = CleanupHelper.getSomething();
if (something != null && someOtherCondition) {
itr.setAttribute("someObject", something);
}
}
}
}
#ContextConfiguration(classes = TestConfig.class)
public class SomeTests extends AbstractTestNGSpringContextTests {
#Test
public void someTest(){
// doSomething
}
}
#Configuration
#ComponentScan(basePackages = "com.some",
excludeFilters = #Filter(type = FilterType.REGEX, pattern = "com.some.else..*"))
public class TestConfig {
}
Above code works... unfortunately onConfigurationSuccess method is invoked after each configuration method.
Try with Annotation Transformers.
You can add it in your testng.xml like any other listener.
And in there you can do things like:
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import org.testng.IAnnotationTransformer;
import org.testng.annotations.ITestAnnotation;
public class TestAnnotationTransformer implements IAnnotationTransformer {
#SuppressWarnings("rawtypes")
#Override
public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) {
if (testMethod.getName().equals("MyTest1"))
annotation.setGroups( new String[] {"GroupA" });
if(ignoreTestDependencies)
annotation.setIgnoreMissingDependencies(true);
}
}
Just an example, but you have many things there to play with.
Just bear in mind that, as I stated in the comments, this runs before runtime, so you won't be able to change things on the go like you would do with a normal listener.
I am trying to integrate AspectJ and SpringBoot. It was running fine until I tried experimenting a bit and used:
#SpringBootApplication
public class TestClassRunner {
#MyAnnotation
public void someDisplay(){
System.out.println("My Display");
}
#Bean(name="dummyString")
public String getString(){
someDisplay();
return "SUCCESS";
}
}
The Aspect class is defined as:
#Aspect
#Component
public class MyAnnotationProcessor{
#Before("#annotation(myTest.MyAnnotation)")
public void aroundSampleCreation(JoinPoint joinPoint) throws Throwable {
System.out.println(joinPoint.getSignature());
System.out.println("Executing the Before call");
}
}
Now this Advice is not getting executed. Is it because of some special character of the #Configuration class (I know #SpringBoot uses that internally)?
I have included all the dependencies and that should not be the cause of this not working.
Any help is highly appreciated.
My code has a bunch of unit tests dealing with some DB that I would like to have reset before each test. I am using the #FlywayTest annotation to perform this reset.
#Test
#FlywayTest
public void unitTest1 {
}
#Test
#FlywayTest
public void unitTest2 {
}
#Test
#FlywayTest
public void unitTest3 {
}
This works fine, but is there a way to do this without having to annotate each test with FlywayTest? I tried this but it doesn't work:
#Before
#FlywayTest
public void setup() {
}
#Test
public void unitTest1 {
}
#Test
public void unitTest2 {
}
#Test
public void unitTest3 {
}
Sorry for late anwser.
At the moment it is not possible but I will think about it if it is possible.
Please add a issue to https://github.com/flyway/flyway-test-extensions/issues
One early design issue was that use made a whole database reset only per test class and use the annotation #FlywayTest on method level only as test exception.
florian
Assuming that my Spring Security and properties are configured properly, I would like to use role name from property like
#PreAuthorize("hasRole('${role.rolename}')")
public void method() {}
I have tried like in above code sample but it does not work (it takes '${role.rolename}' String as role to compare)
If I switch to
#PreAuthorize("hasRole('ROLE_ADMIN')")
public void method() {}
it works just fine.
My motivation to such usage is better flexibility in application tests on various environments.
Try to remove '' signs:
#PreAuthorize("hasRole(${role.rolename})")
public void method() {}
EDIT. I am sure that there is a better way, but as a workaround you can call some method on some bean:
#Component("appVariablesHolder")
public class AppVariablesHolder {
#Value("${role.rolename}")
private String someRole;
public String getSomeRole() {
return this.someRole;
}
}
#PreAuthorize("hasRole(#appVariablesHolder.getSomeRole())")
public void method() {}
I've found that you can just grab the propertyResolver and pull values directly from that, instead of writing your own class as was suggested by #Maksym.
Exammple:
#PreAuthorize("hasRole(#environment.getProperty('role.rolename')")
public void method() {}
Building on other answers here, one thing that tripped me up was not setting the context on the OAuth2MethodSecurityExpressionHandler.
Make sure that in your MethodSecurityConfig you're loading the context for the answers above to work.
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
#Autowired
private ApplicationContext context;
#Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
OAuth2MethodSecurityExpressionHandler handler = new OAuth2MethodSecurityExpressionHandler();
handler.setApplicationContext(context);
return handler;
}
}
Then you can successfully access
#PreAuthorize("hasRole(#environment.getProperty('role.rolename')")
public void method() {}
I read about Structuring Unit Tests with having a test class per class and an inner class per method. Figured that seemed like a handy way to organize the tests, so I tried it in our Java project. However, the tests in the inner classes doesn't seem to be picked up at all.
I did it roughly like this:
public class DogTests
{
public class BarkTests
{
#Test
public void quietBark_IsAtLeastAudible() { }
#Test
public void loudBark_ScaresAveragePerson() { }
}
public class EatTests
{
#Test
public void normalFood_IsEaten() { }
#Test
public void badFood_ThrowsFit() { }
}
}
Does JUnit not support this, or am I just doing it wrong?
You should annontate your class with #RunWith(Enclosed.class), and like others said, declare the inner classes as static:
#RunWith(Enclosed.class)
public class DogTests
{
public static class BarkTests
{
#Test
public void quietBark_IsAtLeastAudible() { }
#Test
public void loudBark_ScaresAveragePerson() { }
}
public static class EatTests
{
#Test
public void normalFood_IsEaten() { }
#Test
public void badFood_ThrowsFit() { }
}
}
public class ServicesTest extends TestBase {
public static class TestLogon{
#Test
public void testLogonRequest() throws Exception {
//My Test Code
}
}
}
Making the inner class static works for me.
In JUnit 5, you simply mark non-static inner classes as #Nested:
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
public class DogTests {
#Nested
public class BarkTests {
#Test
public void quietBark_IsAtLeastAudible() { }
#Test
public void loudBark_ScaresAveragePerson() { }
}
#Nested
public class EatTests {
#Test
public void normalFood_IsEaten() { }
#Test
public void badFood_ThrowsFit() { }
}
}
I think some of the answers might be for older versions of JUnit. In JUnit 4 this worked for me:
#RunWith(Suite.class)
#Suite.SuiteClasses({ DogTests.BarkTests.class, DogTests.EatTests.class })
public class DogTests
{
public static class BarkTests
{
#Test
public void quietBark_IsAtLeastAudible() { }
#Test
public void loudBark_ScaresAveragePerson() { }
}
public static class EatTests
{
#Test
public void normalFood_IsEaten() { }
#Test
public void badFood_ThrowsFit() { }
}
}
I've had success with Nitor Creation's Nested Runner as well.
How to use Nitor Creation's Nested Runner
There is a post explaining it here:
Add this dependency:
<dependency>
<groupId>com.nitorcreations</groupId>
<artifactId>junit-runners</artifactId>
<version>1.2</version>
<scope>test</scope>
</dependency>
And a #RunWith to your test:
import com.nitorcreations.junit.runners.NestedRunner
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
#RunWith(NestedRunner.class)
public class RepositoryUserServiceTest {
public class RegisterNewUserAccount {
public class WhenUserUsesSocialSignIn {
public class WhenUserAccountIsFoundWithEmailAddress {
#Test
public void shouldThrowException() {
assertTrue(true);
}
}
}
}
}
PS: The example code has been taken and modified from the above blog post
I just ran across this posting (11 years later) regarding the testing of inner classes. An inner class can be trivially converted to equivalent static form only if the class should have been static in the first place. Static inner classes are not really inner classes because there is no enclosing this. They have exactly the same semantics (except for visibility restrictions) as top-level classes.
To test a "true" inner class [one that depends on its enclosing instance] you need to use the interface that the Java language provides for creating inner class instances outside the scope of the enclosing class. That interface includes an extra parameter in each constructor which is the enclosing instance. In this way, the Java compiler converts an inner class to a special top-level class with a mangled name (lots of $ signs) and augmented constructors. The same transformation can be performed at the source level. In principle, these transformed classes can be tested but it is a complex process because the tested program has transformed syntax and the test code must construct a (mock) object that serves as the enclosing instance.
Another way to test true inner classes is to write an executable method contract for each method consisting of an executable logical pre-condition and an executable logical post-condition. Then these executable contracts can be evaluated in the course of running a conventional top-level test that invokes the inner class methods.
In practice, I typically settle for the indirect testing of inner class methods in the course of top-level testing. Writing and testing executable contracts for all methods is a more rigorous, albeit significantly more expensive, alternative.