import org.junit.Test; import org.springframework.context.support.ClassPathXmlApplicationContext; public class IngesterCircularReferencesTest { @Test public void circularReferencesTest() { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(); context.setAllowCircularReferences(false); String[] configLocations = new String[] { "/your-beans.xml" }; context.setConfigLocations(configLocations); context.refresh(); context.close(); } }
New ideas pass through three periods:
1) It can’t be done.
2) It probably can be done, but it’s not worth doing.
3) I knew it was a good idea all along!
- Arthur C. Clarke
Showing posts with label Spring. Show all posts
Showing posts with label Spring. Show all posts
Thursday, 19 June 2014
How to test circular dependencies in Spring
This will raise an exception if your dependencies have circular dependency problem
Thursday, 30 January 2014
Access private fields in unit tests
First of all, let me say out louder, you need to design your code to be testable, so you test your private fields through your public methods.
But, ("buts" are the reasons why humans are still programming instead of the computer itself, so be happy here) sometimes you want to and should alter some private fields in order to test all the possible boundaries.
Often private fields can be modified through public getter and setters or using the class constructor and in those cases the tests are easy to create and everybody is happy.
But when you use external frameworks like Spring, it may be possible that you do not have control over injected private fields.
I already explain how to mock spring components in your tests without the need of maintaining and creating ad-hoc test spring configuraitons in a previous post, here I will show you how to modify a private variable for your tests.
Let speak code:
We do not have control over the apiUsers String, so we have couple of straightforward options, one is to create a Spring configuration for your test, modify the Spring context and mock the property, two is to create a setter to change the value of the property from your test.
I discourage from creating public assessors only for you tests, it is confusing for other people looking at your code and creating and maintaing Spring configurations for your tests can be a pain.
I know what you are thinking, "if I cannot do either of the above I'm going to get fired, my girlfriend will leave me and my life is finished", but don't you worry, I'm here to show you another option ;)
You can create a groovy class with a static method to assess your private field in your test :
And use it in your unit test:
Of course you can do the same in java changing the visibility of the field with reflection, but I think the groovy solution can be a cleaner and easier way.
Now, I ll finish this post with the following recommendation:
Do not use this solution unless you really really really need to modify private variables to unit test your class!
But, ("buts" are the reasons why humans are still programming instead of the computer itself, so be happy here) sometimes you want to and should alter some private fields in order to test all the possible boundaries.
Often private fields can be modified through public getter and setters or using the class constructor and in those cases the tests are easy to create and everybody is happy.
But when you use external frameworks like Spring, it may be possible that you do not have control over injected private fields.
I already explain how to mock spring components in your tests without the need of maintaining and creating ad-hoc test spring configuraitons in a previous post, here I will show you how to modify a private variable for your tests.
Let speak code:
import javax.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import com.google.common.collect.ImmutableSet; @Service public class SomeService { @Value("${whitelist.api.users:A,B,C}") private String apiUsers; private ImmutableSet<String> acceptableAPIBUsers; @PostConstruct public void init() { acceptableAPIBUsers = ImmutableSet.copyOf(apiUsers.replaceAll(" ", "").split(",")); } public boolean isAnAcceptableUser(String user) { return user == null ? false : acceptableAPIBUsers.contains(user.toUpperCase()); } }
We do not have control over the apiUsers String, so we have couple of straightforward options, one is to create a Spring configuration for your test, modify the Spring context and mock the property, two is to create a setter to change the value of the property from your test.
I discourage from creating public assessors only for you tests, it is confusing for other people looking at your code and creating and maintaing Spring configurations for your tests can be a pain.
I know what you are thinking, "if I cannot do either of the above I'm going to get fired, my girlfriend will leave me and my life is finished", but don't you worry, I'm here to show you another option ;)
You can create a groovy class with a static method to assess your private field in your test :
import groovy.transform.CompileStatic @CompileStatic class SomeServiceAccessor { public static void setApiUsers(SomeService someService,String apiUsers){ someService.@apiUsers = apiUsers } }
And use it in your unit test:
import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import org.junit.Before; import org.junit.Test; public class SomeServiceTest { private SomeService service; @Before public void setUp() { service = new SomeSercvice(); SomeSercviceAccessor.setApiUsers(service, "pippo,pluto,bungabunga"); service.init(); } @Test public void testIsNotApiUser() { assertThat(service.isAnRTBUser(""), is(false)); assertThat(service.isAnRTBUser(null), is(false)); assertThat(service.isAnRTBUser("random"), is(false)); } @Test public void testIsRTBUser() { assertThat(service.isAnRTBUser("pippo"), is(true)); assertThat(service.isAnRTBUser("PIPPO"), is(true)); assertThat(service.isAnRTBUser("pluto"), is(true)); assertThat(service.isAnRTBUser("bungabunga"), is(true)); } }
Of course you can do the same in java changing the visibility of the field with reflection, but I think the groovy solution can be a cleaner and easier way.
Now, I ll finish this post with the following recommendation:
Do not use this solution unless you really really really need to modify private variables to unit test your class!
Etichette:
@Value,
groovy,
Spring,
test private fields,
test spring property,
unit test
Wednesday, 15 January 2014
Testing Spring components with Mockito
Be able to unit test your spring components without the need of loading the full spring-context with its ad-hoc test configurations it is ,in my opinion, a great advantage because it's clean, easy to maintain, faster to write, smooth to alter.
A way to achieve this goal is to use Mockito and tell him to replace the @Autowired components in the class you want to test, with Mocks ( or Spies ).
Here an example.
We have a service called SalaryService that guess what, is calculating a hypothetical net salary based on the employee id passed. Easy concept.
The service required two collaborators, one, the EmployeeDAO, to retrieve the gross salary and a second one, the TaxCalculator, to apply some taxes based on the gross salary.
EmployeeDAO is a classical service that is in charge of retrieving information from a persistence storage and it will look like this more or less.
TaxCalculator will need a TaxDao to retrieve taxes information and it will then operate some sort of boring and long calculation in order to return the taxes.
Now, we want to unit test the SalaryService class. We should not to be bothered by DAOs and databases setup of any sort. In this UNIT test, we don't care here what the TaxCalculator is doing.
What we want is to test that our SalaryService is behaving as expected and that it is able to correctly use the work of its collaborators.
Here is how we do it with Mockito. We mark the class we want to test with @InjectMocks and we mark with @Mock all of its collaborators ( or @Spy if you need a real implementation ).
Lastly we need to tell our Unit framework, to operate the required Mockito injections before starting the test and we do this with MockitoAnnotations.initMocks(this);.
In the test we need to mock the expected operations so that we can concentrate on the actual logic we want to test inside the SalaryService .
It is simple and efficient and hopefully it will be useful for someone else out there.
A way to achieve this goal is to use Mockito and tell him to replace the @Autowired components in the class you want to test, with Mocks ( or Spies ).
Here an example.
We have a service called SalaryService that guess what, is calculating a hypothetical net salary based on the employee id passed. Easy concept.
The service required two collaborators, one, the EmployeeDAO, to retrieve the gross salary and a second one, the TaxCalculator, to apply some taxes based on the gross salary.
package com.marco.springmockito; import java.math.BigDecimal; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class SalaryService { private static final BigDecimal minimumSalary = new BigDecimal(20000); @Autowired private EmployeeDAO employeeDAO; @Autowired private TaxCalculator taxCalculator; public BigDecimal getNetSalary(long employeeId) { BigDecimal netSalary = null; BigDecimal grossSalary = employeeDAO.getAnnualSalary(employeeId); BigDecimal taxes = taxCalculator.calculateTaxes(grossSalary); if (taxedSalaryIsGreaterThanMinimumSalary(grossSalary)) { netSalary = grossSalary.subtract(taxes); } else { netSalary = grossSalary; } return netSalary; } private boolean taxedSalaryIsGreaterThanMinimumSalary(BigDecimal taxedSalary) { return taxedSalary.compareTo(minimumSalary) == 1; } }
EmployeeDAO is a classical service that is in charge of retrieving information from a persistence storage and it will look like this more or less.
package com.marco.springmockito; import java.math.BigDecimal; import org.springframework.stereotype.Component; @Component public class EmployeeDAO { public BigDecimal getAnnualSalary(long employeeId) { // conncetTODB // run select for employeeId; return new BigDecimal(70000); } }
TaxCalculator will need a TaxDao to retrieve taxes information and it will then operate some sort of boring and long calculation in order to return the taxes.
package com.marco.springmockito; import java.math.BigDecimal; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class TaxCalculator { @Autowired private TaxDao taxDao; public BigDecimal calculateTaxes(BigDecimal salary) { BigDecimal result = salary.multiply(taxDao.getTaxPercentageForYear(2014)); // some other weird calculation .... return result; } }
Now, we want to unit test the SalaryService class. We should not to be bothered by DAOs and databases setup of any sort. In this UNIT test, we don't care here what the TaxCalculator is doing.
What we want is to test that our SalaryService is behaving as expected and that it is able to correctly use the work of its collaborators.
Here is how we do it with Mockito. We mark the class we want to test with @InjectMocks and we mark with @Mock all of its collaborators ( or @Spy if you need a real implementation ).
Lastly we need to tell our Unit framework, to operate the required Mockito injections before starting the test and we do this with MockitoAnnotations.initMocks(this);.
In the test we need to mock the expected operations so that we can concentrate on the actual logic we want to test inside the SalaryService .
package com.marco.springmockito; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; import static org.mockito.Mockito.when; import java.math.BigDecimal; import org.junit.Before; import org.junit.Test; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; public class SalaryServiceTest { private static final long UserId = 123l; @InjectMocks private SalaryService salaryService; @Mock private EmployeeDAO employeeDAO; @Mock private TaxCalculator taxCalculator; @Before public void init() { MockitoAnnotations.initMocks(this); } @Test public void testMinimumSalary() { BigDecimal annualSalary = new BigDecimal(10000); when(employeeDAO.getAnnualSalary(UserId)).thenReturn(annualSalary); when(taxCalculator.calculateTaxes(annualSalary)).thenReturn(new BigDecimal(1000)); BigDecimal actual = salaryService.getNetSalary(UserId); assertThat(actual.compareTo(new BigDecimal(10000)), is(0)); } @Test public void testMaximumSalary() { BigDecimal annualSalary = new BigDecimal(80000); when(employeeDAO.getAnnualSalary(UserId)).thenReturn(annualSalary); when(taxCalculator.calculateTaxes(annualSalary)).thenReturn(new BigDecimal(8000)); BigDecimal actual = salaryService.getNetSalary(UserId); assertThat(actual.compareTo(new BigDecimal(72000)), is(0)); } }
It is simple and efficient and hopefully it will be useful for someone else out there.
Thursday, 27 June 2013
Intercept an @annotation with Aspetcj in Spring
Intercepting a method call marked with an @Annotation using AspectJ and Spring it's easy enough and it's a good approach in terms of flexibility, scalability and design.
First thing you need to do is include the dependencies. In case of maven the following will do it.
Second, we need to create the annotation that we will use to mark the methods in the business logic.
Now, we need to create an interceptor. In this case (@After) it will be triggered when the method intercepted is finished.
For the full list of pointcuts and advises see the following pointcuts and advise
Activate the aspectj and the interceptor in Spring adding the following in your application-context.xml
And of course, remember to load it in your spring configuration classes
All done, now you can mark all the methods you want to intercept with your annotation and you will see the magic happening.
- It's flexible because in the case you want to intercept a different method, you just have to move your annotation somewhere else.
- It's scalable because if you want to intercept more than one method, you just need to add the annotation in other methods.
- It results also in a good and clean code.
First thing you need to do is include the dependencies. In case of maven the following will do it.
<!-- Dependencies for AspectJ and Spring AOP --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.6.11</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.6.11</version> </dependency>
Second, we need to create the annotation that we will use to mark the methods in the business logic.
package com.marco.aspect; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface CommitTransaction { }
Now, we need to create an interceptor. In this case (@After) it will be triggered when the method intercepted is finished.
For the full list of pointcuts and advises see the following pointcuts and advise
package com.marco.aspect; import javax.inject.Inject; import org.apache.log4j.Logger; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.springframework.stereotype.Component; import com.marco.some.package.SomeClass; import com.marco.some.package.SomeBean; @Aspect @Component public class CommitTransactionInterceptor { private static final Logger LOGGER = Logger.getLogger(CommitTransactionInterceptor.class); @Inject private SomeBean someBean; @After("@annotation(com.marcot.CommitTransaction)") public void after() { LOGGER.debug("An invocation to " + SomeClass.class.getSimpleName() + " has been intercepted."); someBean.sendSomeEmail(); } }
Activate the aspectj and the interceptor in Spring adding the following in your application-context.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true" /> <bean id="commitTransactionInterceptor" class="com.marco.aspect.CommitTransactionInterceptor"/> </beans>
And of course, remember to load it in your spring configuration classes
@Configuration @ImportResource({ "classpath:application-context.xml" }) public class YourSpringConfiguration { .... }
All done, now you can mark all the methods you want to intercept with your annotation and you will see the magic happening.
package com.marco.business.logic; public class SomeLogic { private static final Logger LOGGER = Logger.getLogger(SomeLogic.class); @CommitTransaction public void executeSomeLogic(Object someObject) { // a transaction finished } }
Etichette:
@annotation,
aop,
aspect,
aspectj,
Spring,
spring aop
Thursday, 15 November 2012
Chain of responsibility using Spring @Autowired List
There is a way in Spring 3.1 to auto populate a typed List which is very handy when you want to push a bit the decoupling and the cleaning in your code.
To show you how it works, I will implement a simple chain of responsibility that will take care of printing some greetings for a passed User.
Let start from the (only) domain class we have, the User:
Then we create an interface that defines the type for our command objects to be used in our chain:
This is the generic class (the template) for a Printer implementation.
The org.springframework.core.Ordered is used to tell the AnnotationAwareOrderComparator how we want our List to be ordered.
You don't need to implement the Ordered interface and to override the getOrder method if you don't need your chain to have an execution order.
Also notice that this abstract class return Ordered.LOWEST_PRECEDENCE, this because I want some Printer commands to just run at the end of the chain and I don't care about their execution order (everything will be clearer after, I promise!).
This is our first real Printer command. I want this to have absolute precedence in the chain, hence the order is HIGHEST_PRECEDENCE.
WelcomePrinter to be executed as first command (After High precedence ones ).
GoodbyePrinter to be executed as second command
These 2 commands need to be executed after the others, but I don't care about their specific order, so I will not override the getOrder method, leaving the GenericPrinter to return Ordered.LOWEST_PRECEDENCE for both.
This is the chain context.
Spring will scan (see the spring-config.xml) the package specified in the config file, it will see the typed (List<Printer>) list, and it will populate the list with an instance of any @Component that implements the type Printer.
To order the List we use AnnotationAwareOrderComparator.INSTANCE that use the getOrder method to re-order the List ( the object with the lowest value has highest priority (somewhat analogous to Servlet "load-on-startup" values)).
The spring-config.xml in the src/main/resources.
Finally, a main class to test our chain.
OUTPUT:
Hope you enjoyed the example. see ya.
To show you how it works, I will implement a simple chain of responsibility that will take care of printing some greetings for a passed User.
Let start from the (only) domain class we have, the User:
package com.marco.springchain; public class User { private final String name; private final char gender; public User(String name, char gender) { super(); this.name = name; this.gender = gender; } public String getName() { return name; } public char getGender() { return gender; } }
Then we create an interface that defines the type for our command objects to be used in our chain:
package com.marco.springchain; public interface Printer { void print(User user); }
This is the generic class (the template) for a Printer implementation.
The org.springframework.core.Ordered is used to tell the AnnotationAwareOrderComparator how we want our List to be ordered.
You don't need to implement the Ordered interface and to override the getOrder method if you don't need your chain to have an execution order.
Also notice that this abstract class return Ordered.LOWEST_PRECEDENCE, this because I want some Printer commands to just run at the end of the chain and I don't care about their execution order (everything will be clearer after, I promise!).
package com.marco.springchain; import org.springframework.core.Ordered; public abstract class GenericPrinter implements Printer, Ordered { public void print(User user) { String prefix = "Mr"; if (user.getGender() == 'F') { prefix = "Mrs"; } System.out.println(getGreeting() + " " + prefix + " " + user.getName()); } protected abstract String getGreeting(); public int getOrder() { return Ordered.LOWEST_PRECEDENCE; } }
This is our first real Printer command. I want this to have absolute precedence in the chain, hence the order is HIGHEST_PRECEDENCE.
package com.marco.springchain; import org.springframework.core.Ordered; import org.springframework.stereotype.Component; @Component public class HelloPrinter extends GenericPrinter { private static final String GREETING = "Hello"; @Override protected String getGreeting() { return GREETING; } @Override public int getOrder() { return Ordered.HIGHEST_PRECEDENCE; } }
WelcomePrinter to be executed as first command (After High precedence ones ).
package com.marco.springchain; import org.springframework.stereotype.Component; @Component public class WelcomePrinter extends GenericPrinter { private static final String GREETING = "Welcome to the autowired chain"; @Override protected String getGreeting() { return GREETING; } @Override public int getOrder() { return 1; } }
GoodbyePrinter to be executed as second command
package com.marco.springchain; import org.springframework.stereotype.Component; @Component public class GoodbyePrinter extends GenericPrinter { private static final String GREETING = "Goodbye"; @Override protected String getGreeting() { return GREETING; } @Override public int getOrder() { return 2; } }
These 2 commands need to be executed after the others, but I don't care about their specific order, so I will not override the getOrder method, leaving the GenericPrinter to return Ordered.LOWEST_PRECEDENCE for both.
package com.marco.springchain; import org.springframework.stereotype.Component; @Component public class CleaningMemoryPrinter extends GenericPrinter { private static final String GREETING = "Cleaning memory after"; @Override protected String getGreeting() { return GREETING; } }
package com.marco.springchain; import org.springframework.stereotype.Component; @Component public class CleaningSpacePrinter extends GenericPrinter { private static final String GREETING = "Cleaning space after"; @Override protected String getGreeting() { return GREETING; } }
This is the chain context.
Spring will scan (see the spring-config.xml) the package specified in the config file, it will see the typed (List<Printer>) list, and it will populate the list with an instance of any @Component that implements the type Printer.
To order the List we use AnnotationAwareOrderComparator.INSTANCE that use the getOrder method to re-order the List ( the object with the lowest value has highest priority (somewhat analogous to Servlet "load-on-startup" values)).
package com.marco.springchain; import java.util.Collections; import java.util.List; import javax.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.annotation.AnnotationAwareOrderComparator; import org.springframework.stereotype.Component; @Component public class PrinterChain { @Autowired private List<Printer> printers; @PostConstruct public void init() { Collections.sort(printers, AnnotationAwareOrderComparator.INSTANCE); } public void introduceUser(User user) { for (Printer printer : printers) { printer.print(user); } } }
The spring-config.xml in the src/main/resources.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd" default-lazy-init="true"> <context:component-scan base-package="com.marco.springchain"/> </beans>
Finally, a main class to test our chain.
package com.marco.springchain; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MainTest { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml"); PrinterChain printerChain = (PrinterChain) context.getBean("printerChain"); printerChain.introduceUser(new User("Marco Castigliego", 'M')); printerChain.introduceUser(new User("Julie Marot", 'F')); } }
OUTPUT:
Hello Mr Marco Castigliego Welcome to the autowired chain Mr Marco Castigliego Goodbye Mr Marco Castigliego Cleaning space after Mr Marco Castigliego Cleaning memory after Mr Marco Castigliego Hello Mrs Julie Marot Welcome to the autowired chain Mrs Julie Marot Goodbye Mrs Julie Marot Cleaning space after Mrs Julie Marot Cleaning memory after Mrs Julie Marot
Hope you enjoyed the example. see ya.
Etichette:
chain of responsability,
design pattern,
ordered autowired list,
Spring
Subscribe to:
Posts (Atom)
