HtmlUnit Class Cast Exception: TextPage cannot be cast to HtmlPage - java

I am trying to test my web page using spring MVC test and HTMLUnit. I need to get Html Page so that I can set value in my page and submit it but I got the following exception. How can I achieve this? Am I proceeding the right way? Please consider me as I am newbie to TDD.
Error Stack Trace:
java.lang.ClassCastException: com.gargoylesoftware.htmlunit.TextPage cannot be cast to com.gargoylesoftware.htmlunit.html.HtmlPage
at com.demo.htmlunit.test.LoginControllerHtmlUnitTest.userLoginTest(LoginControllerHtmlUnitTest.java:51)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:233)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:87)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:176)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
And my Test Class is:
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
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.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.htmlunit.MockMvcWebConnection;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlPasswordInput;
import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput;
import com.gargoylesoftware.htmlunit.html.HtmlTextInput;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("classpath:applicationContext.xml")
#WebAppConfiguration
public class LoginControllerHtmlUnitTest {
#Autowired
private WebApplicationContext context;
private WebClient webClient;
#Before
public void setup() {
System.out.println("In set Up");
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
webClient = new WebClient();
webClient.setWebConnection(new MockMvcWebConnection(mockMvc));
}
#After
public void cleanup() {
this.webClient.closeAllWindows();
}
#Test
public void userLoginTest() {
try {
// Load the Login Form
System.out.println("In User Login Test");
HtmlPage createLoginFormPage = webClient
.getPage("http://localhost:8080/htmlunitdemo/login");
System.out.println("createLoginFormPage:"+createLoginFormPage);
// Setting Values in the Login form
HtmlForm form = createLoginFormPage.getHtmlElementById("loginForm");
HtmlTextInput usernameInput = createLoginFormPage
.getHtmlElementById("username");
usernameInput.setValueAttribute("admin");
HtmlPasswordInput passwordInput = createLoginFormPage
.getHtmlElementById("passcode");
passwordInput.setText("admin123");
HtmlSubmitInput submit = form.getOneHtmlElementByAttribute("input",
"type", "submit");
// Submitting Form
HtmlPage newPage = submit.click();
System.out.println("New Page:" + newPage.asXml());
} catch (Exception e) {
e.printStackTrace();
}
}
}
applicationContext.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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"
default-lazy-init="true">
<context:component-scan base-package="com.demo.htmlunit.controller" />
<mvc:annotation-driven />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>

The problem is that HTML Unit is not able to cast incompleted HTML Pages (some unclosing tags, for example). So, I could solve this error using HTMLParser which is included in HTMLUnit's packages (I'm using 2.36.0v). HTMLParser completes and handles this kind of casting errors.
//Web client creation.
Page page = webClient.getPage(url);
HtmlPage tmpPage = HTMLParser.parseHtml(page.getWebResponse(), webClient.getCurrentWindow());
// use tmpPage here

HtmlSubmitInput submitBtn = currentPage.getFirstByXPath("//input[#value='Search']");
currentPage = submitBtn.click();

HtmlUnit doesn't care at all about the applicationContext.xml or your Java server code. All it matters to it is the output the server generates. If the output is random text then HtmlUnit will assume it is fetching a text file and will create a TextPage to process it. If the output is HTML then HtmlUnit will assume it is getting an HTML file and create an HtmlPage to hold the result. Based on your question you clearly need the latter.
So verify the output from your server application (http://localhost:8080/htmlunitdemo/login) and make sure it outputs valid HTML code.

replace code line:
HtmlPage newPage = submit.click();
with:
TextPage newPage = submit.click();

I do not know if I already find the solution. The error occurs when the button is Submit, not if it is a button type.
I solved it by adding a button and executing it.
HtmlElement buttonCustom = (HtmlElement) page.createElement("button");
buttonCustom.setAttribute("type", "submit");
buttonCustom.setAttribute("name", "submit");
buttonCustom.setAttribute("value", "Load");
form.appendChild(buttonCustom);

Related

ArrayIndexOutOfBoundsException when accessing the getter on an object created by Spring's class converter

I'm converting one object to another object, but when I try to use the getter on the object that was created, I'm getting an ArrayIndexOutOfBoundsException.
The data is a simple String in the field and is on a very straight-forward object.
I've gotten this same issue with both Spring Boot 2.1.1 & 2.1.7.
Note: To replicate the issue, I have to run using mvn test, mvn install, or use Eclipse' code coverage tool. Using Eclipse's Run or Debug utils succeeds without error.
Exception:
[ERROR] storeWithEncryption(com.forms.service.SpringConversionServiceTest) Time elapsed: 0.003 s <<< ERROR!
java.lang.ArrayIndexOutOfBoundsException: 1
at com.forms.service.SpringConversionServiceTest$To.<init>(SpringConversionServiceTest.java:45)
at com.forms.service.SpringConversionServiceTest.storeWithEncryption(SpringConversionServiceTest.java:26)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:365)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:273)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:238)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:159)
at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:384)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:345)
at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:126)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:418)
Test Class
package com.forms.service;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.convert.ConversionService;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import com.forms.Application;
#RunWith(SpringRunner.class)
#ActiveProfiles("test")
#SpringBootTest(classes = { Application.class })
public class SpringConversionServiceTest {
#Autowired
private ConversionService conversionService;
#Test
public void storeWithEncryption() throws Exception {
From from = new From();
from.bob = "nope";
from.bob2 = "yep";
new To(conversionService.convert(from, To.class));
}
public static final class From {
String bob;
String bob2;
}
public static final class To {
public To() {
// TODO Auto-generated constructor stub
}
public To(To convert) {
this.bob = convert.bob;
this.bob2 = convert.bob2;
}
String bob;
String bob2;
}
}
FromToConverter
package com.forms.service;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
import com.forms.service.SpringConversionServiceTest.From;
import com.forms.service.SpringConversionServiceTest.To;
import com.forms.service.converter.AbstractReflectionConverter;
#Component
public class FromToConverter extends AbstractReflectionConverter implements Converter<From, To> {
public To convert(From from) {
To to = new To();
try {
// 1 to 1 conversions
conversionByReflection(from, to);
} catch (IllegalAccessException e) {
throw new IllegalArgumentException("The source external Header cannot be converted into an internal Header", e);
}
return to;
}
}
Application.java
package com.forms;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
#SpringBootApplication
#ImportResource({ "classpath:spring/camel-context.xml" })
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Pom:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.7.RELEASE</version>
</parent>
In order to get around this issue, I had to change from using spring's reflective ConversionService methods to just manually plugging in the values in the converter.
I won't be marking this as the solution as it doesn't really fix the issue if you need to use reflection, but I'm putting it here to serve as a work-around.

UISpec4J tests in Eclipse are not found

I am trying to run tests using the UISpec4J library, but Eclipse says it can not find them. I have tried restarting Eclipse, cleaning the project, etc.
The class gives no errors and I have followed the examples given on the website.
package com.health.gui;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.uispec4j.Button;
import org.uispec4j.Panel;
import org.uispec4j.UISpec4J;
import org.uispec4j.UISpecTestCase;
import org.uispec4j.Window;
import org.uispec4j.interception.WindowInterceptor;
import com.health.gui.input.xmlwizard.XmlFilePanel;
public class TestXmlFilePanel extends UISpecTestCase {
static {
UISpec4J.init();
}
private Panel panel;
#BeforeClass
public void setUp() {
panel = new Panel(new XmlFilePanel());
}
#Test
public void editWithoutSelectedTest() {
Button edit = panel.getButton("Edit selected");
Window popup = WindowInterceptor.run(edit.triggerClick());
popup.titleEquals("Warning!");
}
}
I get the following stacktrace:
junit.framework.AssertionFailedError: No tests found in com.health.gui.TestXmlFilePanel
at junit.framework.Assert.fail(Assert.java:57)
at junit.framework.TestCase.fail(TestCase.java:227)
at junit.framework.TestSuite$1.runTest(TestSuite.java:100)
at junit.framework.TestCase.runBare(TestCase.java:141)
at junit.framework.TestResult$1.protect(TestResult.java:122)
at junit.framework.TestResult.runProtected(TestResult.java:142)
at junit.framework.TestResult.run(TestResult.java:125)
at junit.framework.TestCase.run(TestCase.java:129)
at junit.framework.TestSuite.runTest(TestSuite.java:255)
at junit.framework.TestSuite.run(TestSuite.java:250)
at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:84)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
I really have no clue what is wrong. Maybe you have some suggestions?
just for fun. you can remove "extends UISpecTestCase" in your class and give it a try see if it works or not :)
Junit 4.X should support annotation well and I didn't see any reason you need to extends UISpecTestCase.

Junit Testing with SpringFramework, without Maven : Error - NoSuchMethodError

I'm new with JUnit - Spring Framework.
What I'm doing is, creating some Tests for my Application. Here is Code what I have did.
#RunWith(SpringJUnit4ClassRunner.class)
public class InspirdTests {
#Autowired
private PlatformBLL platform;
#Autowired
private WebApplicationContext webAppContext;
#Before
public void settingUp(){
System.out.println("Before SetUp");
}
#Test
public void setUp() throws Exception{
System.out.println("Before : " + platform);
platform.getAllProjectsForPlatform(null);
System.out.println("After : " + platform);
}
}
and the Stack Trace
java.lang.NoSuchMethodError: org.junit.runner.notification.RunNotifier.testAborted(Lorg/junit/runner/Description;Ljava/lang/Throwable;)V
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.invokeTestMethod(SpringJUnit4ClassRunner.java:155)
at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:61)
at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:54)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:33)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:45)
at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:52)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:97)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
I'm just blocked, Im stucked with it, i just cant move ahead.
What I have tried:
A lot google, but the result is as it is.
I had made some blank Methods for Testing, Still Result is as it is.
I have added JUnit-4.12.jar into WEB-INF/lib/
I have added Junit 4 into Java Build Path
Guys please Help me to Find out Solution for it.
Include spring-test and junit jars in your eclipse buildpath.
import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
#ContextConfiguration(locations = { "classpath:/conf/applicationContext.xml"})
#RunWith(SpringJUnit4ClassRunner.class)
public class MongoRepositoryImplTest {
#Autowired
MongoRepositoryImpl mongoRepositoryImpl;
#Test
public void testGetMongoConnectionFromFactory() {
...
}
...
Config file should look like:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">
<context:component-scan base-package="com.client.impl" />
<bean id="mongoRepositoryImpl" class="com.client.impl.MongoRepositoryImpl">
<constructor-arg name="connectionName" value="testCases"/>
</bean>
</beans>

junit: NullPointer on injected bean when testing controller with mockmvc

So I have this test case:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("classpath:rest-context-test.xml")
public class CustomerControllerTest {
private MockMvc mockMvc;
#Before
public void setup() {
this.mockMvc = MockMvcBuilders
.standaloneSetup(new CustomerController()).build();
}
#Test
public void testGetCustomerById() throws Exception {
mockMvc.perform(get("/customers/{ccid}", 1)).andExpect(status().isOk())
.andExpect(content().contentType("application/json"))
.andExpect(jsonPath("$.ccid").value("1"));
}
}
That loads rest-context-test.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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd">
<bean id="customerServiceImpl"
class="myorg.service.impl.MockCustomerServiceImpl" />
</beans>
With the hope of being able to AutoWire customerServiceImpl into my controller:
#Controller
#RequestMapping("customers")
public class CustomerController {
private static Logger Logger = LoggerFactory
.getLogger(CustomerController.class);
#Autowired
#Qualifier("customerServiceImpl")
private CustomerService customerService;
#RequestMapping(value = "/{ccid}", method = RequestMethod.GET, produces = "application/json")
#ResponseStatus(HttpStatus.OK)
#ResponseBody
public Customer getCustomerById(#PathVariable Integer ccid)
throws BadRequestException, ServerErrorException,
ResourceNotFoundException {
Customer c = null;
try {
c = customerService.getCustomer(ccid);
} catch (IllegalArgumentException iae) {
// HTTP 400
Logger.error("Invalid arguments submitted", iae);
throw new BadRequestException();
} catch (CsspException ce) {
// HTTP 500
Logger.error("Server error", ce);
throw new ServerErrorException();
}
if (c == null) {
// HTTP 404
throw new ResourceNotFoundException();
}
return c;
}
}
But my unit test is throwing the following trace:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:965)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:844)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:689)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:829)
at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:66)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:168)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:136)
at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:141)
at myorg.rest.controller.CustomerControllerTest.testGetCustomerById(CustomerControllerTest.java:41)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.lang.NullPointerException
at myorg.rest.controller.CustomerController.getCustomerById(CustomerController.java:134)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle (ServletInvocableHandlerMethod.java:104)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod (RequestMappingHandlerAdapter.java:745)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal (RequestMappingHandlerAdapter.java:686)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:953)
... 38 more
This null pointer is thrown when the Controller tries to access customerService:
#Autowired
#Qualifier("customerServiceImpl")
private CustomerService customerService;
Why isn't my MockCustomerServiceImpl being AutoWired into the Controller?
Note: package names have been changed to protect the innocent
From Spring documentation:
The "webAppContextSetup" loads the actual Spring MVC configuration resulting in a more complete integration test. Since the TestContext framework caches the loaded Spring configuration, it helps to keep tests running fast even as more tests get added. Furthermore, you can inject mock services into controllers through Spring configuration, in order to remain focused on testing the web layer.
The "standaloneSetup" on the other hand is a little closer to a unit test. It tests one controller at a time, the controller can be injected with mock dependencies manually, and it doesn’t involve loading Spring configuration. Such tests are more focused in style and make it easier to see which controller is being tested, whether any specific Spring MVC configuration is required to work, and so on. The "standaloneSetup" is also a very convenient way to write ad-hoc tests to verify some behavior or to debug an issue.
From this I understand that, if I need an .xml as a Spring configuration file to be loaded, then I need to go with the "webAppContextSetup". If I just need very simple tests with my Controller, without the need of a Spring configuration, then I go with the "standaloneSetup" approach. In your case, I think you need the "webAppContextSetup".
You forgot to create your mock objects and then inject them into your controller like so
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("classpath:rest-context-test.xml")
public class CustomerControllerTest
{
#Mock
private CustomerService customerService;
#InjectMocks
private CustomerController customerController;
private MockMvc mockMvc;
#Before
public void setup()
{
MockitoAnnotations.initMocks(this);
this.mockMvc = MockMvcBuilders
.standaloneSetup(customerController).build();
}
#Test
public void testGetCustomerById() throws Exception
{
mockMvc.perform(get("/customers/{ccid}", 1)).andExpect(status().isOk())
.andExpect(content().contentType("application/json"))
.andExpect(jsonPath("$.ccid").value("1"));
}
}
It helped me to fix the NullPointerException by adding annotations #RunWith(SpringRunner.class) ,#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) and #AutoConfigureMockMvc
Here is code that worked for me-
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#AutoConfigureMockMvc
public class MyTestClass {
#Autowired
private MockMvc mockMvc;
#Test
public void myClassController() throws Exception {
Object obj = new Object();
obj.setA(1);
obj.setB(2);
obj.setC(3);
ObjectMapper mapper = new ObjectMapper();
String jsonString = mapper.writeValueAsString(obj); // this is the json body
mockMvc.perform(post("/ENDPOINT")
.contentType(MediaType.APPLICATION_JSON)
.content(jsonString))
.andDo(print())
.andExpect(status().isOk());
}

Spring JUnit test keeps return nullpointerexception on my service class

UPDATE 25-11-2012
Hi it seems that my context files was in the wrong 'classpath' They had to be in the test classpath. I solved this by adding a folder called resources to the src/test/ folder. In here I could put my application contexts. I have also removed the #TestExecutionListeners from the test. I also needed to add some dependencies to my pom file for javax/servlet/serlvetException and such. If anyone is interested my code can be seen at Github, under the branch issue9.
Question [Solved]
I have made a simple application, by using spring 3. I have made a service class which uses a DAO class to map things to and from the database, by using the simple JDBC template.
My problem is when i am trying to make an integration test on these classes, it return a NullPointerException (See Stacktrace). It is really annoying since I can't seem to find the answer, so I hope you guys can help me out. Below I have posted all my different files.
Stacktrace
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.115 sec <<< FAILURE!
test(dk.martinrohwedder.blog.test.ArticleServiceTest) Time elapsed: 0.009 sec <<< ERROR!
java.lang.NullPointerException
at dk.martinrohwedder.blog.service.ArticleService.getFiveLastArticles(ArticleService.java:30)
at dk.martinrohwedder.blog.test.ArticleServiceTest.test(ArticleServiceTest.java:57)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:30)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:53)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:123)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:104)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:164)
at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:110)
at org.apache.maven.surefire.booter.SurefireStarter.invokeProvider(SurefireStarter.java:175)
at org.apache.maven.surefire.booter.SurefireStarter.runSuitesInProcessWhenForked(SurefireStarter.java:107)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:68)
ArticleServiceTest
package dk.martinrohwedder.blog.test;
import dk.martinrohwedder.blog.domain.Article;
import dk.martinrohwedder.blog.service.ArticleService;
import java.util.ArrayList;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.transaction.annotation.Transactional;
/**
*
* #author Martin Rohwedder
*/
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations={"classpath:test-context.xml"})
#TestExecutionListeners
#TransactionConfiguration(defaultRollback = true)
#Transactional
public class ArticleServiceTest {
#Autowired(required = true)
private ArticleService articleService;
//private EmbeddedDatabase db;
#Before
public void setUp() {
//EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
//db = builder.setType(EmbeddedDatabaseType.HSQL).setName("blog").addScript("classpath:create-db.sql").addScript("classpath:test-data.sql").build();
//articleService.getArticleDao().setDataSource(db);
//articleService = new ArticleService();
}
#After
public void tearDown() {
//articleService.getArticleDao().setDataSource(null);
//db.shutdown();
//articleService = null;
}
#Test
public void test()
{
ArrayList<Article> articles = articleService.getFiveLastArticles();
int number = articles.size();
assertEquals(3, number);
}
}
ArticleService
package dk.martinrohwedder.blog.service;
import dk.martinrohwedder.blog.domain.Article;
import dk.martinrohwedder.blog.repository.ArticleDao;
import java.util.ArrayList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
*
* #author Martin Rohwedder
* #since 22-11-2012
* #version 1.0
*/
#Service("articleService")
public class ArticleService {
#Autowired(required = true)
private ArticleDao articleDao;
public ArticleDao getArticleDao() {
return articleDao;
}
public void setArticleDao(ArticleDao articleDao) {
this.articleDao = articleDao;
}
public ArrayList<Article> getFiveLastArticles()
{
ArrayList<Article> articles = (ArrayList) articleDao.selectAllArticles();
if (articles.size() > 5) {
articles = (ArrayList) articles.subList(articles.size() - 6, articles.size());
}
return articles;
}
}
ArticleDao
package dk.martinrohwedder.blog.repository;
import dk.martinrohwedder.blog.domain.Article;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
/**
*
* #author Martin Rohwedder
* #since 22-11-2012
* #version 1.0
*/
#Repository
public class ArticleDao implements IArticleDao {
private JdbcTemplate jdbcTemplate;
#Autowired(required = true)
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
#Override
public List<Article> selectAllArticles() {
String sql = "select article_id, headline from article";
return this.jdbcTemplate.query(sql, new ArticleMapper());
}
#Override
public Article selectArticle(int articleId) {
throw new UnsupportedOperationException("Not supported yet.");
}
#Override
public void insertArticle(Article article) {
throw new UnsupportedOperationException("Not supported yet.");
}
#Override
public void updateArticle(Article article) {
throw new UnsupportedOperationException("Not supported yet.");
}
#Override
public void deleteArticle(int articleId) {
throw new UnsupportedOperationException("Not supported yet.");
}
/**
* Article Mapper is responsible for map all rows found in a sql
* statement to Article objects.
*/
private static final class ArticleMapper implements RowMapper<Article> {
#Override
public Article mapRow(ResultSet rs, int rowNum) throws SQLException {
Article article = new Article();
article.setId(rs.getInt("article_id"));
article.setHeadline(rs.getString("headline"));
return article;
}
}
}
test-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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd">
<context:component-scan base-package="dk.martinrohwedder.blog" />
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/views/" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="embeddedDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.hsqldb.jdbc.JDBCDriver"/>
<property name="url" value="jdbc:hsqldb:mem:blog"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<jdbc:embedded-database id="dataSource" type="HSQL"/>
<jdbc:initialize-database data-source="embeddedDataSource">
<jdbc:script location="classpath:create-db.sql"/>
<jdbc:script location="classpath:test-data.sql"/>
</jdbc:initialize-database>
</beans>
create-db.sql
create database if not exists blog;
use blog;
drop table if exists article;
create table article
(
article_id int unsigned not null auto_increment,
headline varchar(30) not null,
primary key (article_id)
);
test-data.xml
insert into article (article_headline)
values ("Artikel 1");
insert into article (article_headline)
values ("Artikel 2");
insert into article (article_headline)
values ("Artikel 3");
Both test-context.xml, create-db.sql and test-data.sql is in the classpath since they are in the package called Other Sources (src/main/resources).
Hopes that anyone can help me out.
Try using
<context:annotation-config/>
instead of
<mvc:annotation-driven />
in your test-context.xml file.
<mvc:annotation-driven/> is a tag added in Spring 3.0 which does the following:
Configures the Spring 3 Type ConversionService (alternative to
PropertyEditors)
Adds support for formatting Number fields with #NumberFormat
Adds support for formatting Date, Calendar, and Joda Time fields with #DateTimeFormat, if Joda Time is on the classpath
Adds support for validating #Controller inputs with #Valid, if a JSR-303 Provider is on the classpath
Adds support for support for reading and writing XML, if JAXB is on the classpath (HTTP message conversion with #RequestBody/#ResponseBody)
Adds support for reading and writing JSON, if Jackson is o n the classpath (along the same lines as #5)
<context:annotation-config/>
Looks for annotations on beans in the same application context it is defined and declares support for all the general annotations like #Autowired, #Resource, #Required, #PostConstruct etc etc.
It looks to me like articleDao is not being set. If you want to use a Spring bean in the test then you can't instantiate the service in your test. Take this line out...
articleService = new ArticleService();

Categories

Resources