简体   繁体   中英

How to unit-test JSP Tags?

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.

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.

Neel is right. You need to mock the ServletContext if you don't want to use the full javaee.jar.

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.

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
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM