i am currently writing Junit-Tests for on OData-Application (a hobby project). In there, I initialize a Servlet with the init() function. In order to receive specific application settings, i use the context.getResource() method.
Here is my code:
#Override
public void init(ServletConfig config) {
try {
super.init(config);
ServletContext context = getServletContext();
URL resourceUrl = context.getResource("/WEB-INF/config.properties");
if (resourceUrl == null) {
throw new ConfigurationException("Unable to find config.properties");
}
Path configFile = Paths.get(resourceUrl.toURI());
Now, I try to mock it. The Servlet itself is easy to mock, but im getting error when i try to mock the "getResource"-functionality. Here is my Junit-(beforeClass) Block:
public static ODataServlet getServlet() throws MalformedURLException {
if (servlet == null) {
servletConfig = new MockServletConfig();
MockServletContext context = new MockServletContext();
Path path = Paths.get("src/test/resources/config.properties");
when(context.getResource("/WEB-INF/config.properties")).thenReturn(path.toUri().toURL());
servlet = new ODataServlet(){
/**
*
*/
private static final long serialVersionUID = 1L;
public ServletContext getServletContext() {
return context; // return the mock
}
};
servlet.init(servletConfig);
}
return servlet;
}
Unfortunately, i always get the Exception:
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
In the line
when(context.getResource("/WEB-INF/config.properties")).thenReturn(path.toUri().toURL());
I dont understand why. the context-Object is a MockedObject (MockServletContext).
Any advice ? Im also thinking changing everytghing to classloader.getResource as a workaround. But actually i like it like this ...
Any help would be much appreciated.
Sephir
UPDATE: SOLVED. After literally only a few minutes in here, some guys pointed out the Issue: MockServletContext context is from the Package org.springframework.mock.web which is not working with the Mockito.
After changing the MockServletContext
MockServletContext context = new MockServletContext();
to
context = Mockito.mock(ServletContext.class);
everything is working.
Big thanks to you Guys (!).
Related
We have migrated our application from weblogic 10.0 to jboss EAP 6.1.0.
While accessing the properties which is loaded in the init() method of the servlet from our EJB, the value returned is null.
Below method is in Ejbbean class:
public void execute() throws EJBException
{
System.out.println("Constants.x in execute ----"+Constants.x);
}
the value printed here is null. Although if we use the same code inside our application anywhere other than EJB, the correct value is returned.
We are loading the properies inside the init method of servlet.
public void init() throws javax.servlet.ServletException
{
ServletContext sContext = this.getServletContext();
try
{
String propFile = sContext.getInitParameter("abc");
Properties prop = new Properties();
FileInputStream inStream = new FileInputStream(propFile);
prop.load(inStream);
Constants.loadValues(prop);
System.out.println("Constants.x in execute ----"+Constants.x);
}
the correct value for static variable x is printed here.
public final class Constants
{
public static String x = null;
public final static void loadValues(Properties prop) throws Exception
{
// the properties are loaded here...
}
}
Whats the reason behind this unexpected behaviour of static variable inside EJB when the same code is working fine elsewhere? This problem was not there in the application when it was deployed on weblogic server.
How can this be fixed?
I got the solution to this problem. jboss-deployment-structure.xml needs to be written for the application with the dependency of the EJB on the WAR.
Reference link:
http://www.mastertheboss.com/jboss-server/jboss-deploy/configuring-jboss-as-7-deployment-order
I have a filter which maps just before the Faces Servlet and populate some Attributes in the HttpSession before it proceeds with the request
if (_clientUser != null && !_clientUser.isEmpty()) {
session.setAttribute(CLIENT_USER_URI_PARAM_NAME, _clientUser);
filterChain.doFilter(servletRequest, servletResponse);
return;
}
Within the URI there are some informations for which Task-flow should be addressed
faces/adf.task-flow?adf.tfId=task-flow-definition-id&adf.tfDoc=/WEB-INF/task-flow-definition-id.xml
After I proceed the request there is a method-call within the bounded task flow which is called before the view (lets call the view MainPage), by making it default activity
<default-activity>doStuff</default-activity>
The Method itself is within a PageFlowScoped Managed Bean, which is added to the task-flow-definition-id.xml
Here is the doStuff Method which is called before the "MainPage"-View
public class Controller{
public void doStuff {
FacesContext ctx = FacesContext.getCurrentInstance();
Map sessionMap = ctx.getExternalContext().getSessionMap();
String clientUser = (String) sessionMap.get(CLIENT_USER_URI_PARAM_NAME);
AppModImpl am = getApplicationModule();
DBTransaction transaction = am.getDBTransaction();
//do more stuff
}
}
public AppModImpl getApplicationModule() {
FacesContext fc = FacesContext.getCurrentInstance();
Application app = fc.getApplication();
ExpressionFactory elFactory = app.getExpressionFactory();
ELContext elContext = fc.getELContext();
ValueExpression valueExp =
elFactory.createValueExpression(elContext, "#{data.AppModDataControl.dataProvider}", Object.class);
AppModImpl am = (AppModImpl) valueExp.getValue(elContext);
return am;
}
Everything works fine till here. But if I try to get the Application Module. There is non.
This application normally doesn't have any DataControl, because is just a root Application which holds different components which have been added by ADFLibrarys, but I added an DataControl to the DataBindings.cpx and a iterator to the MainPagePageDef (just to include a DataControl in the bindings) but still no result.
Do you have any advice for me how I can access the Application Module? FacesServlet should have been already created the necessary FacesContext by the time the Managed Bean is called or does it only create a new FacesContext the Time an actual Page (jspx/jsf) loads?
I've found myself an answer:
Here is the Block Post which helped me figure it out.
http://andrejusb.blogspot.de/2012/02/how-to-fix-data-control-initialization.html
i have a problem is:
java.lang.Exception: ServletConfig has not been initialized
I searched for it nearly 2 days but i did not have a solution for me. Every one had said that
super.init(config) must be used. I have tried this, but there is nothing change for me.
My init method;
#Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
AppServiceServlet service = new AppServiceServlet();
try {
service.getir();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
AutoCheckStatus.autoCheckStatus(600000);
}
and my AppServiceServlet;
public List<SswAppServiceDto> getir() throws Exception {
try {
final WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(this
.getServletContext());
setiAppServiceBusinessManager((IAppServiceBusinessManager) context.getBean(BEAN_ADI));
List<SswAppService> result = getiAppServiceBusinessManager().getir();
List<SswAppServiceDto> list = DtoConverter.convertSswAppServiceDto(result);
for (int i = 0; i < result.size(); i++) {
AppService appService = new AppService();
appService.setServiceName(result.get(i).getName());
appService.setUid(result.get(i).getServiceUid());
appService.setHost(result.get(i).getHost());
appService.setPort((int) result.get(i).getPort());
SystemConfiguration.appServiceList.put(appService.getUid(), appService);
}
return list;
} catch (RuntimeException e) {
throw new Exception(e.getMessage(), e.getCause());
}
}
The exception is thrown in this line;
final WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
in AppServiceServlet and says:
java.lang.Exception: ServletConfig has not been initialized.
Pls help.
This call:
AppServiceServlet service = new AppServiceServlet();
Instantiates a servlet instance via new, which circumvents the normal, container managed creation of a servlet. As such, critical class variables (for example, the servlet config) don't get properly initialized.
Later on, you are making a call to getServletContext, which simply redirects to getServletConfig().getServletContext(), but because the servlet configuration was never completed you get an exception.
Infact, calling new on a servlet the way you are is non-compliant with the specification - servlets are supposed to be maintained by the web app container. The proper way to launch a startup servlet is either via configuration in your web.xml file, or via annotation.
I created web-service,where i am getting url params , which i am setting it to Object.
after it when i want to set to facesContext it is giving me NULL.I got Suggestion to implement AbstractFacesServlet.java class in project but any idea how can ?
And this is what code i am using _
public class ReserRes extends ServerResource {
#Post("xml")
public void $post() throws Throwable {
...........
.....
FacesHelper.setValueBindingObject("SelectedOtaReservationBean",
reservationBean);
......
}
And setValueBindingObject(,,) is
public static final void setValueBindingObject(String expression,
final Object value) {
FacesContext facesContext = FacesContext.getCurrentInstance();
if (facesContext == null) // Always throwing NULL
throw new NullPointerException(
"Could not get a reference to the current Faces context");
Application application = facesContext.getApplication();
ValueBinding vb = application.createValueBinding(expression);
vb.setValue(facesContext, value);
}
In this i am not interacting with any .jsp or any kind of UI. i am getting params and binding with object. Is this wrong or any way to implement FacesContext for ws.?
I got one suggestion http://cwiki.apache.org/MYFACES/access-facescontext-from-servlet.html to use this class. any buddy know how can i implement or set object to FacesContext using this?
Thanx
EDIT: You can ignore most of what I have written below:
I am getting a null value of context when I do the following in some TestNG code:
public void setupNonTrivialObjects() {
TestFixture.context = new MockServletContext("test");
}
Am I supposed to do something more to make a MockServletContext object that is not null?
ORIGINAL: I am learning to use the Stripes Framework with TestNG.
I am following the example here (but adapting it to my own code): http://www.stripesframework.org/display/stripes/Unit+Testing under the heading Approach 2
I have this test:
public class SeedSearchActionBeanTest {
#Test
public void seedSearchTest() throws Exception {
// Setup the servlet engine
MockServletContext ctx = TestFixture.getServletContext();
MockRoundtrip trip = new MockRoundtrip(ctx, SeedSearchActionBean.class);
trip.setParameter("input", "sdfs");
trip.execute();
SeedSearchActionBean bean = trip.getActionBean(SeedSearchActionBean.class);
Assert.assertEquals(bean.getInput(),"sdfs");
Assert.assertEquals(trip.getDestination(), "/results.jsp");
}
}
This "TestFixture" not really sure what that is.
public class TestFixture {
private static MockServletContext context;
#BeforeSuite
public void setupNonTrivialObjects() {
TestFixture.context = new MockServletContext("test");
// Add the Stripes Filter
Map<String,String> filterParams = new HashMap<String,String>();
filterParams.put("ActionResolver.Packages", "net.sourceforge.stripes");
context.addFilter(StripesFilter.class, "StripesFilter", filterParams);
// Add the Stripes Dispatcher
context.setServlet(DispatcherServlet.class, "StripesDispatcher", null);
}
public static MockServletContext getServletContext() {
return TestFixture.context;
}
}
I get this error
FAILED: seedSearchTest
java.lang.NullPointerException
at net.sourceforge.stripes.mock.MockRoundtrip.getUrlBindingStub(MockRoundtrip.java:384)
at net.sourceforge.stripes.mock.MockRoundtrip.<init>(MockRoundtrip.java:96)
at net.sourceforge.stripes.mock.MockRoundtrip.<init>(MockRoundtrip.java:82)
at sempedia.tests.action.SeedSearchActionBeanTest.seedSearchTest(SeedSearchActionBeanTest.java:17)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
I guess this line MockServletContext ctx = TestFixture.getServletContext(); is not working, I am wondering if there is something I am missing, particularly, is there something I have to do in the web.xml?
The mistake is with this line:
filterParams.put("ActionResolver.Packages", "net.sourceforge.stripes");`
This should be (in my case):
filterParams.put("ActionResolver.Packages", "action");
Essentially you are setting the package name where the ActionBeans are found. It seems very obvious once you know it.
You seem to be testing whether you've set up Stripes action bean creation and parameter passing which no doubt have been tested extensively by those developing the Stripes Framework. I tend to test the load/save/etc business logic (services) called from my actions.