Reputation: 2894
I have a custom JSP tag
public class HappyTag extends TagSupport { ... }
and now I need to test it.
So I've created a simple JUnit test:
@Test
public void testTag() {
HappyTag tag = new HappyTag();
}
and I get the following error:
java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file javax/servlet/jsp/tagext/TagSupport
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
(.....)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
I am using maven to build and test my application, tags included. My current dependencies of the tags sub-module are:
<dependencies>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>6.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
plus some dependencies from the parent module:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>javax.portlet</groupId>
<artifactId>portlet-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.portletfaces</groupId>
<artifactId>portletfaces-bridge-impl</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>el-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>el-impl</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
Those dependencies are enough to compile and use the tags in my JSP. They are not enough to test the tag :-(
So, what did I do wrong?
Kindest regards,
Q.
Upvotes: 5
Views: 3938
Reputation: 2484
If you are using Spring Test you can do it in the following way:
public class MyCustomTagTest {
private MockServletContext mockServletContext;
private MockPageContext mockPageContext;
@BeforeEach
void setUp() {
mockServletContext = new MockServletContext();
mockPageContext = new MockPageContext(mockServletContext);
}
@Test
void testMyTag() throws Exception {
MyCustomTag myCustomTag = new MyCustomTag();
myCustomTag.setPageContext(mockPageContext);
myCustomTag.doStartTag();
String output = ((MockHttpServletResponse) mockPageContext.getResponse()).getContentAsString();
// do your assertions on output
}
}
Upvotes: 1
Reputation: 895
Neel is right. You need to mock the ServletContext if you don't want to use the full javaee.jar.
Upvotes: 0
Reputation: 1413
You can use mockito and or power mock to mock servlet context and jsp page context. Mock each method that your tag calls to properly function(doTag). You need to add the mocking framework and javax.el as test dependencies.
Upvotes: 0
Reputation: 2100
the Java EE maven dependencies only provides stubs to help compile code which requires those interfaces. IT doe snot provide the implementation. Hence you cannot run them. You need to either work around to mock the behavior (which might end up refactoring your code a lot), or you need to functionally run the test using a dependency which provides a full implementation of the API's. Maybe this answer might help.
Upvotes: 1