我正在尝试创建并运行针对我的Servlet的单元测试,该Servlet在通过一些在线教程后访问DataSource http://fandry.blogspot.com/2011/03/junit-based-integration-testing-with.html
注意:过去我有一个类似的帖子,从中得到了使用jndi-simple
api的想法,正如其中一个答案所建议的那样。
但是我在测试执行期间遇到异常。
异常
Running com.study.mockito.controllers.ProductControllerTest
Failed to bind JNDI context....
java.lang.NullPointerException
at java.util.Hashtable.put(Hashtable.java:514)
at org.osjava.sj.jndi.StaticHashtable.put(StaticHashtable.java:84)
at org.osjava.sj.jndi.AbstractContext.bind(AbstractContext.java:337)
at org.osjava.sj.jndi.AbstractContext.rebind(AbstractContext.java:361)
at org.osjava.sj.jndi.AbstractContext.rebind(AbstractContext.java:368)
at javax.naming.InitialContext.rebind(InitialContext.java:427)
at org.osjava.sj.jndi.DelegatingContext.rebind(DelegatingContext.java:76)
at javax.naming.InitialContext.rebind(InitialContext.java:427)
at com.study.mockito.controllers.ProductControllerTest.setUpClass(ProductControllerTest.java:40)
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:606)
我已使用META-INF / context.xml在Tomcat容器中配置了DataSource,它运行正常,没有任何问题。我可以在我的JSP webapp中检索和显示数据而不会出现任何问题。
context.xml中
<Context antiJARLocking="true" path="/mockito-web">
<!-- PostgreSQL Datasource -->
<Resource auth="Container" driverClassName="org.postgresql.Driver" factory="org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory" maxActive="50" maxIdle="10" maxWait="-1" name="jdbc/istore-db" password="postgres" type="javax.sql.DataSource" url="jdbc:postgresql://mydb-server:5432/istore-db" username="postgres"/>
</Context>
的pom.xml
<dependency>
<groupId>simple-jndi</groupId>
<artifactId>simple-jndi</artifactId>
<version>0.11.4.1</version>
<scope>test</scope>
</dependency>
的src /测试/资源/ jndi.properties
java.naming.factory.initial=org.osjava.sj.SimpleContextFactory
org.osjava.sj.root=target/test-classes
org.osjava.jndi.delimiter=/
org.osjava.sj.jndi.shared=true
的src /测试/资源/ jdbc.properties
istore-db.type=javax.sql.DataSource
istore-db.driver=org.postgresql.Driver
istore-db.url=jdbc:postgresql://mydb-server:5432/istore-db
istore-db.user=postgres
istore-db.password=postgres
ProductContollerTest.java
public class ProductControllerTest {
private HttpServletRequest request;
private HttpServletResponse response;
private ProductController controller;
private RequestDispatcher rd;
private ServletContext appContext;
private ProductService productService;
private Product product;
@BeforeClass
public static void setUpClass() {
try {
InitialContext ctxt = new InitialContext();
DataSource dataSource = (DataSource) ctxt.lookup("jdbc/istore-db");
// rebind for alias if needed
ctxt.rebind("jdbc/istore-db", dataSource);
} catch (Exception ex) {
System.out.println("Failed to bind JNDI context....");
ex.printStackTrace();
}
}
@Before
public void setUp() {
controller = new ProductController();
request = mock(HttpServletRequest.class);
response = mock(HttpServletResponse.class);
rd = mock(RequestDispatcher.class);
appContext = mock(ServletContext.class);
productService = mock(ProductService.class);
product = mock(Product.class);
}
@Test
public void testProcessRequest() throws ServletException, IOException {
when(productService.getProduct(anyInt())).thenReturn(product);
when(request.getServletContext()).thenReturn(appContext);
when(appContext.getRequestDispatcher(anyString())).thenReturn(rd);
//make an actual call
controller.doGet(request, response);
//verify that the method is getting called
verify(rd).forward(request, response);
}
}
ProductController.java
@WebServlet(name = "ProductController", urlPatterns = {"/product.htm"})
public class ProductController extends HttpServlet {
private static final int PRODUCT_ID = 301;
@Resource(name = "jdbc/istore-db")
protected DataSource dataSource;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
processRequest(request, response);
}
public void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("Into the ProductController...");
//fetch the product from the db based on productId parameter
Product product = new ProductService(dataSource).getProduct(PRODUCT_ID);
request.setAttribute("product", product);
RequestDispatcher rd = request.getServletContext().getRequestDispatcher("/jsp/product.jsp");
rd.forward(request, response);
}
}
答案 0 :(得分:0)
我们遇到这个问题有两个原因:JNDI为多个数据源定义了相同的名称;包含的密码&#39;#&#39;破坏JNDI的信件