Testing on JWebUnit - servlets

I am trying to do integration test on my servlets with the JWebUnit framework. All I've done is importing the two jar files needed (jwebunitcore and jwebunit-htmlunit-plgin) into my class path. Here is the code:
package com.ec.projectName.server;
import static org.junit.Assert.*;
import net.sourceforge.jwebunit.junit.JWebUnit;
import net.sourceforge.jwebunit.util.TestingEngineRegistry;
import org.junit.Before;
import org.junit.Test;
public class ViewTest {
#Before
public void setUp() throws Exception {
JWebUnit.setTestingEngineKey(TestingEngineRegistry.TESTING_ENGINE_HTMLUNIT);
JWebUnit.setBaseUrl("http://localhost:8080/projectName");
}
#Test
public void test() {
JWebUnit.beginAt("View.html");
JWebUnit.assertTitleEquals("View result");
JWebUnit.assertFormPresent();
JWebUnit.assertFormElementPresent("preferred_name");
JWebUnit.assertFormElementPresent("zip_Code");
}
}
Finally I run this as junit test and my servlet is running in the browser, but I am still getting an error as result!
Am I doing something wrong here?

Related

Spring MockMvc doesn't contain cookies

I have a controller protected with HTTP Basic authentication.
I setup the app to use session cookies and it works.
However when I test the controller using MockMvc, a successful authentication does not give me any cookie.
Web configuration:
package world.pyb.spring.cookiesdemo;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
#Configuration
#EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("admin").password("argentina").roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
//#formatter:off
http.httpBasic()
.and().authorizeRequests().antMatchers(HttpMethod.GET, "/hello").authenticated()
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.ALWAYS);
//#formatter:on
}
}
Simple controller:
package world.pyb.spring.cookiesdemo;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class HelloController {
#RequestMapping("/hello")
public String index() {
return "Greetings from Spring Boot!";
}
}
Simple controller test that doesn't give me the session cookie:
package world.pyb.spring.cookiesdemo;
import static org.hamcrest.Matchers.equalTo;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.cookie;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
#RunWith(SpringRunner.class)
#SpringBootTest
#AutoConfigureMockMvc
public class HelloControllerTest {
#Autowired
private MockMvc mvc;
#Test
public void getHello() throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/hello")
.with(SecurityMockMvcRequestPostProcessors.httpBasic("admin", "argentina"))
)
// prints "Cookies = []"
.andDo(MockMvcResultHandlers.print())
.andExpect(cookie().exists("JSESSIONID"))
.andExpect(status().is2xxSuccessful())
.andExpect(content().string(equalTo("Greetings from Spring Boot!")));
}
}
Related questions:
Why does Spring MockMvc result not contain a cookie?
Unit Testing /login in Spring MVC using MockMvc
Spring MVC testing (security Integration test), JSESSIONID is not present
Some answers suggest not to use MockMvc but I'd like to keep using it if possible.
As shown in the question's code, MockMvcResultMatcher includes support for cookies.
This will work fine, as long as the controller under test itself delivers the cookie. The problem here is that the cookie is delivered by Spring Security, which is a wrapper around your controller. MockMvc is testing your controller directly, and not testing your controller running in its real HTTP server, as would be required to test the security-layer cookies.
That's why TestRestTemplate, which invokes your controller in its full server context, delivers a more thorough test environment.
Notice however that as of Spring 5, the newer approach to running-server API testing is based on WebTestClient.

No InputStream specified when use spring-mvc-test andDo() method

recently when i do my work using spring-mvc-test-framework,code like this:
this.mockMvc.perform(MockMvcRequestBuilders.get("/manage/bill/detail/{id}","5507c2240cf2bc43ba2367bd").accept(MediaType.ALL)).andExpect(MockMvcResultMatchers.status().isOk()).andDo(MockMvcRestDocumentation.document("index"));
then i got this error.
java.lang.IllegalArgumentException: No InputStream specified
at org.springframework.util.Assert.notNull(Assert.java:112)
at org.springframework.util.FileCopyUtils.copy(FileCopyUtils.java:106)
at org.springframework.util.FileCopyUtils.copyToByteArray(FileCopyUtils.java:156)
at org.springframework.restdocs.mockmvc.MockMvcOperationRequestFactory.createOperationRequest(MockMvcOperationRequestFactory.java:83)
at org.springframework.restdocs.mockmvc.RestDocumentationResultHandler.handle(RestDocumentationResultHandler.java:93)
at org.springframework.test.web.servlet.MockMvc$1.andDo(MockMvc.java:155)
I searched and find no answers.
can anybody tell me why this happens?
Now I got another solution.
actually I use Spring MVC test example in its offical reference http://docs.spring.io/spring-restdocs/docs/1.0.0.RELEASE/reference/html5/#getting-started-build-configuration-maven-packaging and use the setUp() method like this:
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build();
the aim is to document api 。Now the another solution is I use apply() method and then problem solved.
first,i changed to :
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
.apply(MockMvcRestDocumentation.documentationConfiguration(this.restDocumentation)).build();
then solved the version problem like this:
spring-restdocs is not recognizing apply()
All my code below:
package com.dream.bwm.test.test;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.restdocs.RestDocumentation;
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation;
import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration
#ContextConfiguration(locations = { "classpath:spring/root-context.xml", "classpath:spring/app-context.xml" })
public class DocsGenerator {
public static String outputDir = "D:\\workspace-bwme\\pro-root\\bwme-backend\\target\\generated-snippets";
#Rule
public final RestDocumentation restDocumentation = new RestDocumentation(outputDir);
#Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
#Before
public void setUp() {
// this.mockMvc =
// MockMvcBuilders.webAppContextSetup(this.context).build();
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
.apply(MockMvcRestDocumentation.documentationConfiguration(this.restDocumentation)).build();
}
// #Test
public void printOnConsole() throws Exception {
this.mockMvc
.perform(
MockMvcRequestBuilders.get("/manage/bill/detail/{id}", "5507c2240cf2bc43ba2367bd").accept(
MediaType.ALL_VALUE)).andDo(MockMvcResultHandlers.print())
.andExpect(MockMvcResultMatchers.status().isOk());// MockMvcRestDocumentation.document("index")
}
#Test
public void writeToDocument() throws Exception {
this.mockMvc
.perform(
RestDocumentationRequestBuilders.get("/manage/bill/detail/{id}", "5507c2240cf2bc43ba2367bd")
.accept(MediaType.ALL)).andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcRestDocumentation.document("index"));
}
}
hope this can give you some help if someone encounters such questions.

RestAssuredMockMvc Connection to http://localhost:8080 refused

I developed a Spring MVC webapp with rest methods. I would love to use RestAssured to create JUnit test classes. From the documentation it looks really simple to do but I'm having some problem instead. Basically I want to use it to avoid a runtime Tomcat instance but the problem is that when I execute the JUnit test class I obtain the following exception:
org.apache.http.conn.HttpHostConnectException: Connection to http://localhost:8082 refused
...
Caused by: java.net.ConnectException: Connection refused
This is my JUnit class:
import static com.jayway.restassured.RestAssured.given;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.web.context.WebApplicationContext;
import com.jayway.restassured.module.mockmvc.RestAssuredMockMvc;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"file:src/test/resources/spring/application-test-config.xml"})
#WebAppConfiguration
public class ExternalControllerTest {
private static final Logger logger = LoggerFactory.getLogger(ExternalControllerTest.class);
#Autowired
WebApplicationContext webApplicationContext;
#Before
public void setUp() throws Exception {
RestAssuredMockMvc.webAppContextSetup(webApplicationContext);
}
#Test
public void addClientDeviceId_Success() {
given().get("/api/test").then().statusCode(200);
}
}
I also tried to configure RestAssuredMockMvc directly with the controller class but the result is the same:
RestAssuredMockMvc.standaloneSetup(new ExternalController());
The controller looks like that:
#Controller
#RequestMapping("/api")
public class ExternalController {
public ExternalController() {
logger.info("ExternalController initialised!");
}
#RequestMapping(value="/test", method = RequestMethod.GET, produces={"application/json", "application/xml"})
public #ResponseBody DmsResponse test(HttpServletResponse response) {
response.setStatus(HttpServletResponse.SC_OK);
return null;
}
}
In this guide http://www.jayway.com/2014/01/14/unit-testing-spring-mvc-controllers-with-rest-assured/ is specified that "The most important aspect is that it’s simpler to get the environment started. You don’t need to bootstrap a container (for example Jetty or Tomcat), you simply initialize RestAssuredMockMvc with a context (for example a controller) and you’re ready to go." So I don't understand where the problem is. Any suggestion?
The war file deployed with Tomcat works fine.
Thanks
You are statically importing the wrong methods. You're importing given from com.jayway.restassured.RestAssured (io.restassured.RestAssured if using version 3.x) but you should statically import the methods from com.jayway.restassured.module.mockmvc.RestAssuredMockMvc (io.restassured.module.mockmvc.RestAssuredMockMvc in version 3.x). Refer to the documentation for more info.

ServletContainerInitializer vs ServletContextListener

I'm trying to register a servlet using servletContainerInitializer but it doesn't seem to work, Maybe it's my code (kindly review it), but I came to wonder about the difference between ServletContainerInitializer and ServletContextListener, because the follwing code runs fine when used as ServletContextListener instead.
From servlet 3.0 specification:
4.4
Configuration methods (adding servlets dynamically):
... or from the onStartup method of a ServletContainerInitializer implementation ...
The ServletContainerInitializer:
package com.marmoush.javaexamples.nullhaus.servlet;
import java.util.Set;
import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
public class MyInit implements ServletContainerInitializer {
public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException {
System.out.println("hello");
ServletRegistration reg = ctx.addServlet("q31","com.marmoush.javaexamples.nullhaus.servlet.Q31");
reg.addMapping("/q31/*");
}
}
The servlet which I'm trying to auto-register:
package com.marmoush.javaexamples.nullhaus.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Q31 extends HttpServlet {
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().println("hello world");
}
}
Original code from nullhaus java examples website "only class name edited" also didn't work!
package com.marmoush.javaexamples.nullhaus.servlet;
import java.util.Set;
import javax.servlet.Servlet;
import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
public class MyInit implements ServletContainerInitializer {
public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException {
try {
Class klass = Class.forName("com.marmoush.javaexamples.nullhaus.servlet.Q31");
Class<Q31> clazz = (Class<Q31>) klass;
Servlet s = ctx.createServlet(clazz);
ServletRegistration.Dynamic d = ctx.addServlet("q31", s);
d.addMapping("/baz/*");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
The ServletContainerInitializer implementation is intented to be bundled in a JAR file which is in turn been dropped in /WEB-INF/lib of the webapp. The JAR file itself should have a /META-INF/services/javax.servlet.ServletContainerInitializer file containing the FQN of the ServletContainerInitializer implementation in the JAR. Please note that this file should thus not be placed in the webapp itself!
This allows webapp module developers to let their JAR file hook on webapp's startup and shutdown cycle. It's true that they could also have used a ServletContextListener with #WebListener for this, but this won't work if the webapp's own web.xml file has a metadata-complete="true" attribute set in <web-app> which means that the webapp shouldn't scan JARs for annotations (which saves startup time).
That the ServletContainerInitializer doesn't work in your particular case can only mean that you're actually not developing a module JAR file, but just a part integral to your own web application. In that case, the ServletContainerInitializer is useless for you and you should be using ServletContextListener instead.
#WebListener
public class Config implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent event) {
// Do stuff during server startup.
}
#Override
public void contextDestroyed(ServletContextEvent event) {
// Do stuff during server shutdown.
}
}
See also:
Map servlet programmatically instead of using web.xml or annotations
Splitting up shared code and web.xml from WAR project to common JAR project
Using special auto start servlet to initialize on startup and share application data
what is the equivalence of contextDestroyed() in ServletContainerInitializer?
Check if you have configured the ServletContainerInitializer propertly. The ServletContainerInitializer class name should be configured inside a file:
META-INF/services/javax.servlet.ServletContainerInitializer
The file should contain just the class name. For Ex in your case it should look like:
com.marmoush.javaexamples.nullhaus.servlet.MyInit
The file (META-INF/services/javax.servlet.ServletContainerInitializer) can be bundled in a library JAR in WEB-INF/lib.
Here is any example which explains.

Get exception when using injection with a simple HelloEJB project

I am now learning EJB and got a problem when testing the Injection functionality. Here is my code (I create an EJB project in Eclipse).
I run the EJB with embedded Glassfish, and run the test(main) independently, but always get this exception:
java.lang.NullPointerException
at com.example.MainUsingInjection.runTest(MainUsingInjection.java:11)
at com.example.MainUsingInjection.main(MainUsingInjection.java:20)
I hope anyone can help me with this. Thank you very much.
HelloSessionBean.java
package com.example;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
#Stateless
#LocalBean
public class HelloSessionBean implements HelloSessionBeanRemote {
public HelloSessionBean() { }
public void helloMethod() {
System.out.println("Hello World!\n");
}
}
HelloSessionBeanRemote.java
package com.example;
import javax.ejb.Remote;
#Remote
public interface HelloSessionBeanRemote {
public void helloMethod();
}
MainUsingJnjection.java
package com.example;
import javax.ejb.EJB;
public class MainUsingInjection {
#EJB(name="HelloSessionBean")
public static HelloSessionBeanRemote bean;
public void runTest() throws Exception {
bean.helloMethod();
}
public static void main(String[] args) {
MainUsingInjection cli = new MainUsingInjection();
try {
cli.runTest();
} catch (Exception e) {
e.printStackTrace();
}
}
}
The stack trace suggests that you've directly launched the main method. In order to use injection in the main class, you must use the application client container.

Resources