How to test JSF bean methods that use session parameters? - unit-testing

I'm having a hard time trying to implement unit tests on my JSF backing bean classes... For instance some of the methods use session or request parameters, obtained using this sort of code:
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("paramKey");.
My question is: how can I test a method which obtains values from the session or request?

What I usually do is to avoid calling static methods into the beans I want to test. That implies your current code to be refactored:
FacesContext.getCurrentInstance().getExternalContext()
.getSessionMap().get("paramKey");
Are there ways to test them with their static method calls? Probably there are, but they led me to a lot of trouble more than help. So at the end I got rid of them and changed my design. Just let a second bean do it (which you'll mock later). In your case, create a #SessionScoped bean which manages that functionality:
#ManagedBean
#SessionScoped
public class SessionBean{
public Object getSessionParam(String paramKey){
FacesContext.getCurrentInstance().getExternalContext()
.getSessionMap().get(paramKey);
}
}
And inject that bean in every single bean that needs it (I usually extend my view/request beans from an abstract bean which has it, so don't have to implement it in every single bean):
#ManagedBean
#RequestScoped
public class RequestBean{
#ManagedProperty(value="#{sessionBean}")
private SessionBean sessionBean;
public void accessSessionParam(){
sessionBean.getSessionParam("name");
}
}
That way you can access static methods easily, via your auxiliary SessionBean. Then, how to test it? Just create a mock of it (using Mockito, for instance):
public class Test{
public void test1(){
SessionBean sb = Mockito.mock(SessionBean.class);
//Mock your 'getSessionParam' method
ValueBean vb = new ValueBean();
Mockito.when(sb.getSessionParam(Mockito.anyString()).thenReturn(vb);
//Create your bean to test and set your mock to it
RequestBean rb = new RequestBean();
rb.setSessionBean(sb);
//here you can test your RequestBean assuming
//sessionBean.getSessionParam()
//will return vb for every single call
}
}

It is possible to mock FacesContext but this is less than ideal. Mockito example:
import javax.faces.context.FacesContext;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
public abstract class ContextMocker extends FacesContext {
private ContextMocker() {}
private static final Release RELEASE = new Release();
private static class Release implements Answer<Void> {
#Override
public Void answer(InvocationOnMock invocation) throws Throwable {
setCurrentInstance(null);
return null;
}
}
public static FacesContext mockFacesContext() {
FacesContext context = Mockito.mock(FacesContext.class);
setCurrentInstance(context);
Mockito.doAnswer(RELEASE)
.when(context)
.release();
return context;
}
}
If your platform supports it, prefer CDI to JSF managed beans. CDI has static dependency checking and injects proxies to prevent scope leak. CDI doesn't support all of JSF's features but it is relatively easy to connect JSF managed beans to CDI where necessary.
JSF managed beans restrict the scope that you inject types into but even that can lead to scope leaks. For example, the #{sessionScope} variable can be injected into a session scope bean even though the object belongs to the request scoped ExternalContext. It is possible to overcome this by writing your own JSF bean proxies.
Note: most of this was written with Java EE 6 in mind; things might have improved with Java EE 7.

Related

CDI Inject in Stateless Session Beans requests

Currently we have an elaborate POJO object structure for handling a webservice request, called a 'processor'.
Remote and Local EJB's and PersistenceContext called during serving this request are initialized in the statless bean and handed to this 'processors' constructor which is re-created during each webservice request.
If I do not want to revert to JNDI lookups deep down in my 'processor' I keep on dragging around all these EJB's through my code.
Enter CDI. I would like to be able to inject these EJB's whenever I need them in this 'processor'.
However, I also noticed this means that the current 'processor' has to become a CDI bean itselve: so, using the #Inject in the Stateless Session Bean that implements the webservice.
When I do this the entiry lifecycle of the processor becomes bound to the bean and not to the request its serving.
Suddenly I have to take into consideration that I should not retain state (other than the injected objects) in the processor, since this state will be shared between multiple webservice invocations. As a programmer, this is not making my life more easy.
So: how should I go about doing this? I've read about the scoping but I'm not sure how / if this would be helping me.
Example, stateless bean:
#Stateless
#WebService
public class ExampleBean {
#Inject
Processor requestScopedInstance;
int beanDependentScopeCounter;
public String sayHello() {
System.out.println( "bean object id: " + this.toString() );
return requestScopedInstance.sayHello(beanDependentScopeCounter++);
}
}
interface:
public interface Processor {
String sayHello(int beanScopedCounter);
}
Implementation:
public class ProcessorImpl implements Processor {
private int requestScopedCounter = 0;
#Override
public String sayHello(int beanScopedCounter) {
return "test, requestScoped: " + requestScopedCounter++ + ", beansScoped: " + beanScopedCounter;
}
}
When I do this the entiry lifecycle of the processor becomes bound to the bean and not to the request its serving that is not correct. That is only the case if you don't use #ApplicationScoped, #SessionScoped, #RequestScoped.
So:
Annotate your processor with #RequestScoped.
You don't need to hand over the EJBs, you can just inject them, where needed.
Use #PostConstruct annotated methods for constructor-code which uses injected objects.
stateless POJOs can be annotated #ApplicationScoped, not stateless POJOs can stay dependent-scoped which is default.
That is made possible because proxies are injected, not actual beans. Using these proxies CDI makes sure that the correct scope is used for your particular calls.

Mock final class and inject it to autowired data member and overcome postConstruct method call

I want to unit test a java class with an autowired final class object, as well as another autowired class that has #PostConstruct method. While it is possible to test them individually, i am not able to combine them together.
This question is an extension to the question on injecting mockito mocks into spring bean
Code to be tested
public class A {
#Autowired
private FinalClass serviceClient;
#Autowired
private ClassWithPostConstructor resourceVerifier;
//no setters or constructors
public String useBothFinalClassAndClassWithPostConstructor() {
//logic to be tested
}
}
Working Test class
#RunWith(PowerMockRunner.class)
#PrepareForTest(FinalClass.class)
public class ATest {
//#org.mockito.Mock //fails to mock final class
#org.powermock.api.easymock.annotation.Mock
private FinalClass serviceClient;
#org.powermock.api.easymock.annotation.Mock
private ClassWithPostConstructor resourceVerifier;
//other mock objects required for mocking the services
//#InjectMocks //fails since mocking final class
private A a;
#Before
public void init() {
a = new A();
//working snippet with setters created in A and without #Autowired here within the test
serviceClient = PowerMock.create(FinalClass.class);
a.setServiceClient(serviceClient);
resourceVerifier = PowerMock.create(ClassWithPostConstructor.class);
a.setClassWithPostConstructor(resourceVerifier);
}
#Test
public void testTheMethodUsingExpectAndVerify() {
//test the functionality here
EasyMock.expect(serviceClient.callService()).andReturn("someMock");
EasyMock.expect(resourceVerifier.verifyFn()).andReturn("success");
PowerMock.replayAll();
A.useBothFinalClassAndClassWithPostConstructor();
PowerMock.verifyAll();
}
}
The above code works with the need for setters in file
Expected Test class
#RunWith(PowerMockRunner.class)
#PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations={"file:spring-configuration/unit-testing-config.xml"})
#PrepareForTest(FinalClass.class)
public class ATest {
#Autowired
private FinalClass serviceClient;
#Autowired
private ClassWithPostConstructor resourceVerifier;
//other mock objects required for mocking the services
private A a;
#Before
public void init() {
a = new A();
}
#Test
public void testTheMethodUsingExpectAndVerify() {
//test the functions here
EasyMock.expect(serviceClient.callService()).andReturn("someMock");
EasyMock.expect(resourceVerifier.verifyFn()).andReturn("success");
PowerMock.replayAll();
A.useBothFinalClassAndClassWithPostConstructor();
PowerMock.verifyAll();
}
}
//spring-configuration/unit-testing-config.xml
//same error even on customer factory
<bean id="resourceVerifier" class="org.powermock.api.easymock.PowerMock" factory-method="createMock">
<constructor-arg type="java.lang.Class" value="com.company...resourceVerifier" />
</bean>
<bean id="resourceVerifier" class="org.powermock.api.easymock.PowerMock" factory-method="createMock">
<constructor-arg type="java.lang.Class" value="com.company...serviceClient" />
</bean>
The above snippet mocks finalClass but calls #PostConstructor of ResourceVerifier.class - What should be done here to overcome this call.
Investigations
It is possible to test autowired files using #InjectMocks without the need for spring context configurations.
#InjectMock fails silently for static and final fields and when failing, it doesn't inject other mocks as well.
It is possible to mock final class using PowerMock's createMock and run the test with PowerMockRunner and #PrepareForTest. But this requires new unnecessary setters to inject the mocks for #Autowired fields.
MockitoAnnotations.#Mock doesn't work along well with PowerMock (especially when mocking final class objects) and can be solved via EasyMock.Annotations.#Mock
EasyMock and PowerMock doesn't have an #InjectMocks annotation to inject the mocks as possible by Mockito (Would have solved the problem in secs).
It is possible to inject autowired spring beans via SpringJUnit4Runner and a separate unit-testing #ContextConfiguration
It is possible to run the same test file with both PowerMockRunner and SpringJUnit4Runner with PowerMockRunnerDelegate
I know that #PostConstruct method will not be executed automatically if mocked in code than by using spring bean creation and injection.
If a wrapper factory bean class is written and used to create the mocks, it injects automatically, but calls the #PostConstruct method as well along with it.
It is not possible to depend on Springockito since it is unreliable at this stage.
But none of these worked since the usecase is a combination of all these.
Possible Solutions
Remove #Autowired fields and use Setter injections so that it is possible by mocking normally using PowerMock(Tested to work) - But it is a convention followed by external team packages - i should try my best to stick to it.
Or set #Autowired to the setters or to constructor
Alternatives?
I don't feel that the classes require reorganisation as they serve their purposes and are well designed as well.
Any other means that doesn't require to keep hands on the class under test - What if i didn't have the permissions to modify this class? i.e., a pure testing library dependent solution.
Not sure whether it is possible by PowerMockito? Haven't tried the combination of PowerMockito with PowerMock.
Hmm,
Not sure whether it is possible by PowerMockito? Haven't tried the combination of PowerMockito with PowerMock.
Seems to me you have a mess in your head and misunderstanding PowerMock/Mockito and EasyMock.
You should never use at same time PowerMockito and PowerMock, because these two classes are PowerMock friendly API for two different mocking frameworks: EasyMock and Mockito. And there is no reason to use they both.
And of course this want work
//#org.mockito.Mock //fails to mock final class
#org.powermock.api.easymock.annotation.Mock
private FinalClass serviceClient;
#org.powermock.api.easymock.annotation.Mock
private ClassWithPostConstructor resourceVerifier;
//other mock objects required for mocking the services
//#InjectMocks //fails since mocking final class
private A a;
Because, you decelerate and create mocks via EasyMock API, but tries to inject it with Mockito Annotation.
You have to choose only one Mocking Framework and use suitable API for it. For now, Mockito + PowerMockito (PowerMock API for Mockito) better fit your requirements.
You may full example how it works on PowerMock github
#RunWith(PowerMockRunner.class)
#PrepareForTest(FinalClass.class)
public class SpringInjectFinalClassExampleTest {
#Mock
private FinalClass finalClass;
#InjectMocks
private MyBean myBean = new MyBean();;
#Test
public void testInjectFinalClass() {
final String value = "What's up?";
when(finalClass.sayHello()).thenReturn(value);
assertEquals(value, myBean.sayHello());
}
}

Unit-testing bean-initialization

I have a #SessionScoped bean that does some initialization at construction by calling various services (accessed via a service-locator). I would like to test if the initialized state of the bean is correct after its creation.
The bean looks something like this:
#ManagedBean
#SessionScoped
public class MyBean extends MyBeanBase {
public MyBean(){
init();
}
private void init(){
//call service-methods to initialize some fields of the bean
}
...
}
The class MyBeanBase contains a singleton-instance of a MyServiceLocator that exposes some services:
#ManagedBean(name="...")
#ApplicationScoped
public class MyServiceLocator{
#EJB
private Service1 service1;
#EJB
private Service2 service2;
...
// getters for services
}
I use the Mockito mocking framework for my unit-tests. My initial idea was to mock the services that get called in the constructor and inject these mocks into the bean instance, but this does not work, because Mockito needs an instance of the class to be able to start mocking, but the service methods get called in the constructor itself.
My second idea was to move the bean-initialization into a #PostConstruct method like this:
#ManagedBean
#SessionScoped
public class MyBean extends MyBeanBase {
private MyType field1;
...
#PostConstruct
private void init(){
//call service-methods to initialize some fields of the bean
field1 = getService1().getValue();
...
}
...
}
I read some other threads discussing this case and suggesting the use of SpringJUnit4ClassRunner and #Autowired, but I'm not 100% sure if this is the correct approach in this case.
So basically what I would like to do is use mocked services to test if the bean gets initialized correctly using those services. My questions are:
What is the best approach for this problem?
Is there a better way to design the bean so that its initialized state can be tested easily?
Does testing the state of the bean even make sense in a unit-test?

PersistenceContextType.EXTENDED inside Singleton

We are using Jboss 7.1.1 in an application mostly generated by Jboss Forge, however we added a repository layer for all domain related code.
I was trying to create a Startup bean to initialize the database state. I would like to use my existing repositories for that.
My repositories all have an extended PersistenceContext injected into them. I use these from my View beans that are #ConversationScoped #Stateful beans, by using the extended context my entities remain managed during a conversation.
First I tried this:
#Startup
#Singleton
public class ConfigBean {
#Inject
private StatusRepository statusRepository;
#Inject
private ZipCode zipCodeRepository;
#PostConstruct
public void createData() {
statusRepository.add(new Status("NEW"));
zipCodeRepository.add(new ZipCode("82738"));
}
}
Example repository:
#Stateful
public class ZipCodeRepository {
#PersistenceContext(PersistenceContextType.EXTENDED)
private EntityManger em;
public void add(ZipCode zipCode) {
em.persist(zipCode);
}
....
}
This ends up throwing an javax.ejb.EJBTransactionRolledbackException on Application startup with the following message:
JBAS011437: Found extended persistence context in SFSB invocation call stack but that cannot be used because the transaction already has a transactional context associated with it. This can be avoided by changing application code, either eliminate the extended persistence context or the transactional context. See JPA spec 2.0 section 7.6.3.1.
I struggled finding a good explanation for this, and actually figured that since EJB's and their injection are handled by proxies all the PersistenceContext injection and propagation would be handled automatically. I guess I was wrong.
However, while on this trail of thought I tried the following:
#Startup
#Singleton
public class ConfigBean {
#Inject
private SetupBean setupBean;
#PostConstruct
public void createData() {
setupBean.createData();
}
#Stateful
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public static class SetupBean {
#Inject
private StatusRepository statusRepository;
#Inject
private ZipCode zipCodeRepository;
public void createData() {
statusRepository.add(new Status("NEW"));
zipCodeRepository.add(new ZipCode("82738"));
}
}
}
This does the trick. All I did was wrap the code in a Stateful SessionBean that is a static inner class of my Singleton bean.
Does anyone understand this behavior? Because while everything works now I'm still a bit estranged as to why it works this way.
A container-managed extended persistence context can only be initiated
within the scope of a stateful session bean. It exists from the point
at which the stateful session bean that declares a dependency on an
entity manager of type PersistenceContextType.EXTENDED is created, and
is said to be bound to the stateful session bean.
From the posted code, it seems ZipCodeRepository isn't itself stateful bean, but you're calling it from one such bean.
In this case, you are initiating PersistenceContextType.TRANSACTION from ConfigBean & propogates through ZipCodeRepository having PersistenceContextType.EXTENDED & it tries to join the transaction, hence the exception.
Invocation of an entity manager defined with PersistenceContext- Type.EXTENDED will result in the use of the existing extended
persistence context bound to that component.
When a business method of the stateful session bean is invoked, if the stateful session bean uses container managed transaction
demarcation, and the entity manager is not already associated with the
current JTA transaction, the container associates the entity manager
with the current JTA transaction and calls
EntityManager.joinTransaction. If there is a different persistence
context already associated with the JTA transaction, the container
throws the EJBException.
While in later case, you're creating a new transaction in SetupBean for each invocation with TransactionAttributeType.REQUIRES_NEW which is of extended type, as it's a stateful bean.
Therefore, adding SetupBean as stateful session bean initiating new transaction for each invocation & later calling ZipCodeRepository doesn't result in exception. ZipCodeRepository will join the same transaction as initiated by SetupBean.

How to cleanly unit test a custom ValueResolver ResolveCore(...) method

I'm trying to unit test a custom ValueResolver (Automapper) but am running into problems because the method it forces me to override is not exposed directly in the custom object we must create. I override the protected method "ResolveCore" but the only public method exposed is "Resolve" which expects a complex "ResolutionResult" automapper object as it's input. In the vein of true unit testing I want to test this object / method in isolation to anything else and don't really want to go the route of firing up automapper with mappings to do this test. Likewise it's not possible to Mock "ResolutionResult" and it seems a very complex object to setup for each test (again requiring creation / association of other Automapper objects).
The only (less than ideal) solution I can come up with (and have seen suggested when Googling for a solution) is to stub a public method inside the class that exposes the protected overriden method. If we must go down this route then so be it, but has anyone else got a better solution that tests the method call in isolation doesn't require a modification of the object we are trying to test?
Example code:
public class CustomResolver : ValueResolver<Supplier, string>
{
protected override string ResolveCore(Custom source)
{
return string.Format("{0} {1}", source.Name, source.Descripton);
}
public string UnitTestStub(Custom source)
{
return ResolveCore(source);
}
}
I wouldn't place a public stub in your class. Instead, I'd just create a simple subclass in my unit test assembly that exposes the call I wanted to test:
public class TestCustomResolver : CustomResolver
{
public string TestResolveCore(Custom source)
{
return this.ResolveCore(source);
}
}
Some of this depends on the unit testing framework you're using too. For example, you could use the InternalsVisibleTo() attribute to expose your internals to your unit tests. However, I would lean towards a simple subclass in your unit tests.