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.
Related
i am using spring cloud's eureka and feign to communicate between some services (lets say A and B). Now id like to unittest my service layer of a single service (A). The problem is, that this service (A) is using a feign client to request some information of the other service (B).
Running the unittests without any special configuration throws the following exception: java.lang.RuntimeException: com.netflix.client.ClientException: Load balancer does not have available server for client: service-b => but i do not want any server to run.
My question is: Is there a way to mock the feign client, so i can unittest my service (A) without running an eureka instance and service (B)?
Edit:
I ended up creating a stub for the feign client. The stub is marked as a primary component to force spring instantiating the stub within my tests.
This is the solution i came up with.
//the feign client
#FeignClient("user")
public interface UserClient {
UserEntity getUser();
}
//the implementation i use for the tests
#Component
#Primary //mark as primary implementation
public class UserClientTestImpl implements UserClient {
#Override public UserEntity getUser() {
return someKindOfUser;
}
}
The question is ... do you even need to mock? I often see that people mention "mock" as the first solution to anything that "should not be part of the unit test". Mocking is a technique, not the solution to everything. (see here).
If you are still at the early stages of your code, just refactor and use something else instead of depending on the concrete instance of the Feign Client. You might use an interface, an abstract class, a trait or whatever you want. Don't depend on the object itself, otherwise you have to "mock it".
public interface IWebClient {
public String get(...);
public String post(...);
}
To the question: but I will have other code that will do exactly the same (except that it will be on the concrete instance of Feign), what do I do then?
Well, you can write a functional test and call an instance of a web server that you can setup locally - or use Wiremock, as mentioned by Marcin Grzejszczak in one of the answers.
public class FeignClientWrapper implements IWebClient {
private feign = something
public String get() {
feign.get( ... )
}
public String post() {
feign.post( ... )
}
}
Unit tests are used to test algorithms, if/else, loops: how units work. Don't write code to make mocks fit - it must be the other way around: your code should have less dependencies, and you should mock only when you need to verify the behavior (otherwise you can use a stub or a fake object): do you need to verify the behavior? Do you need to test that a particular method gets called in your code? Or that a particular method gets called with X, Y, and Z for 3 times in a row? Well, then yes, mocking is ok.
Otherwise, use a fake object: what you want is to test just the call/response and maybe the status code. All you probably want is to test how your code reacts to different outputs (e.g., the field "error" is present or not in a JSON response), different status codes (assuming that the Client documentation is right: 200 OK when GET, 201 when POST, etc).
Mocking a feign client is really useful in microservice component tests. You want to test one microservice without having to start all the other microservices.
If you're using Spring (and it looks like you are), the #MockBean annotation together with a bit of Mockito code will do the job.
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment =
SpringBootTest.WebEnvironment.DEFINED_PORT)
public class TestYourComponent {
#Configuration
#Import({YourConfiguration.class})
public static class TestConfiguration {
}
#MockBean
private UserClient userClient;
#Test
public void someTest()
{
//...
mockSomeBehavior();
//...
}
private void mockSomeBehavior() {
Mockito.doReturn(someKindOfUser).when(userClient).getUser();
}
}
If you need to use a mock you can use Wiremock to stub the response for a given request - http://wiremock.org/stubbing.html. That way you will do integration tests with real HTTP requests sent. For unit testing the answer from #Markon is very good.
What is the difference between mocking service and assign instance of class to service?
For example:
class MyService {
def CallServiceMethod(){
my business logic
}
}
class MyController {
def myService
def callServiceMethod(){
myService.callServiceMethod()
}
}
#TestFor(MyController)
class MyControllerTests {
#Before
void setup() {
controller?.myService = new MyService()
vs
controller?.myService = mockFor(MyService)
}
void testCallServiceMethod(){
controller.callServiceMethod()
}
}
Any one help me please?
When using Spring, you typically lose a lot of behavior if you create a new instance of a class that's registered as a Spring bean. Beans often have multiple other beans dependency-injected into them and those fields would be null in a plain new instance, and various annotations trigger wrapping the bean instance in one or more proxies that add extra checks and behavior before and/or after your methods are called - and that won't happen with a new instance. These proxies include the transactional wrapper you get with #Transactional, the cache checks from #Cacheable, and security checks from #Secured and other Spring Security annotations.
In addition, Grails adds a lot of code to most artifacts (in particular domain classes and controllers). Most of that is added to the bytecode, but some is added at runtime to the metaclass. Although the bytecode is there for a new instance, it often needs a final bit of configuration at runtime. For example there are over 100 GORM methods added to domain classes, but they don't work by themselves and need to be "hooked up" to the current GORM implementation (Hibernate, MongoDB, etc.) This is why you sometimes see an error like "this class was used outside of a Grails application" - the class for some reason didn't have a GORM impl attached, so it can't function.
mockFor and annotations like #TestFor and #Mock don't add all of this behavior, but they do add a large subset of it, and they add mocked but realistic implementations of many methods. The goal is to give the collaborators of your class under test enough run-app-like behavior that they work essentially like they would in a real app, so you can focus on the class being tested without having to think about configuring a test database, or fake web requests and responses, etc.
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.
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.
I have a class (lets call it A) that:
In the constructor takes a config and based on it, creates a stub of
a web service and stores a reference to it in a private field.
Has a few methods that call web methods and some stuff inbetween.
I started to create a unit test that:
Creates an instance of a class A with a dummy configuration.
Through reflection it injects the mocked web service stub.
Although that web service has plenty of methods.
Should I mock them all (in every test, with different data)?
Or maybe I should create another layer that encapsulates only the web methods that are being used?
Or there is another approach?
You should create a wrapper interface around your webservice, and make your class under test take a dependency on that interface, rather than directly on the webservice; you can then mock the interface. Only make that interface expose the methods of the webservice that you find interesting. This is known as a facade pattern, and is detailed here.
Without having a clue about what you're testing, aim for something like this:
public interface IWebserviceWrapper
{
Whatever DoStuff(int something);
}
public class WebserviceWrapper : IWebserviceWrapper
{
private WebService _theActualWebservice;
public WebserviceWrapper(Webservice theService)
{
_theActualWebService = theService;
}
public Whatever DoStuff(int something)
{
return _theActualWebservice.DoSomething(something);
}
}
Then your test would look like this (in this case, using MOQ)
public void Test_doing_something()
{
Mock<IWebserviceWrapper> _serviceWrapperMock = new Mock<IWebserviceWrapper>();
_serviceWrapperMock.SetUp(m => m.DoStuff(12345)).Returns(new Whatever());
var classUnderTest = new ClassUnderTest(_serviceWrapperMock.Object);
var result = classUnderTest.Dothings(12345);
Assert.Whatever....
}
Short answer Yes :). Long answer you should use some kind of mocking lib for example: http://code.google.com/p/mockito/ and in your unit test mock the WS stub and pass it to the tested class. That is the way of the force :)
When you unit test a class, you always want to make sure to only test that class and not include its dependencies. To do that, you will have to mock your WS to have it return dummy data when methods are called. Depending on your scenarios, you do not have to mock ALL the methods for each test, I would say only those that are used.
For an example about mocking, you can read this article: http://written-in-codes.blogspot.ca/2011/11/unit-tests-part-deux.html