0

У меня есть простой объект области запроса, содержащий инъецированного Принципала, чтобы я мог определить идентификатор текущего пользователя. Этот компонент затем вводится в сервлет, а сервлет использует компонент для отображения идентификатора пользователя. Например:Интеграционное тестирование с инициатором ввода CDI

Интерфейс:

public interface UserManager { 

    public String getCurrentUserName(); 

} 

Реализация:

@RequestScoped 
public class CdiUserManager implements UserManager { 

    @Inject 
    private Principal principal; 

    public CdiUserManager() { 

    } 

    @Override 
    public String getCurrentUserName() { 

     String name = null; 

     if(principal != null && principal.getName() != null){ 
       name = principal.getName(); 
     } 

     return name; 
    } 

} 

Сервлет:

@WebServlet({"/public/user", "/authenticated/user"}) 
public class UserServlet extends HttpServlet { 

    @Inject 
    private UserManager manager; 

    public UserServlet() { 
     super(); 
    } 

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 

     response.getWriter().write("UserName: " + manager.getCurrentUserName()); 
    } 

} 

Сервлет отображается как для аутентифицированного, так и для неавторизованного доступа. У меня есть web.xml, настроенный с соответствующими ограничениями безопасности, поэтому для аутентифицированного URL требуется только базовая аутентификация.

У меня также есть файл EAR. Приложение.xml в EAR включает веб-модуль с сервлетом и управляемым компонентом, а также роль безопасности, определенную в web.xml. Кроме того, у меня есть файл ibm-application-bnd.xml, который сопоставляет роль безопасности в web.xml и application.xml специальному предмету ALL_AUTHENTICATED_USERS.

У меня есть пустой файл beans.xml в каталоге WEB-INF WAR.

У меня есть две проблемы на данный момент, которые я не могу решить.

1) Когда я обращаюсь к общедоступному URL-адресу в качестве пользователя, не прошедшего проверку подлинности, я ожидал, что либо инициатор ввода, либо вызов принципала.getName() будут иметь значение NULL или какое-либо другое идентифицируемое значение ... т.е. "НЕОПРЕДЕЛЕННЫЙ" , В настоящее время я получаю NPE с трассировкой стека ниже. Если я получаю доступ к аутентифицированному URL-адресу и регистрируюсь через базовую аутентификацию, сервлет возвращает мое имя пользователя, как ожидалось. Я не уверен, что стандарт должен быть возвращен в этом случае, но я думаю, что это ошибка?

java.lang.NullPointerException 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:95) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:56) 
at java.lang.reflect.Method.invoke(Method.java:620) 
at org.apache.webbeans.component.BuildInOwbBean$BuildInBeanMethodHandler.invoke(BuildInOwbBean.java:273) 
at [internal classes] 
at org.javassist.tmp.java.lang.Object_$$_javassist_1.getName(Object_$$_javassist_1.java) 
at com.testing.cdi.CdiUserManager.getCurrentUserName(CdiUserManager.java:23) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:95) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:56) 
at java.lang.reflect.Method.invoke(Method.java:620) 
at org.apache.webbeans.intercept.InterceptorHandler.invoke(InterceptorHandler.java:327) 
at [internal classes] 
at com.testing.cdi.CdiUserManager_$$_javassist_0.getCurrentUserName(CdiUserManager_$$_javassist_0.java) 
at com.testing.cdi.UserServlet.doGet(UserServlet.java:31) 
at javax.servlet.http.HttpServlet.service(HttpServlet.java:575) 
at javax.servlet.http.HttpServlet.service(HttpServlet.java:668) 
at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1285) 
at [internal classes] 

2) Второй вопрос, который у меня есть, - как интегрировать тест с использованием введенного принципала? Я в настоящее время использую Arquillian и я построил метод развертывания, который выглядит следующим образом:

@Deployment 
public static EnterpriseArchive createDeployment() { 

    EnterpriseArchive ear = ShrinkWrap.create(EnterpriseArchive.class, CONTEXT_ROOT + ".ear"); 
    WebArchive war = ShrinkWrap.create(WebArchive.class, CONTEXT_ROOT + ".war"); 

    war.addPackages(true, UserManager.class.getPackage()); 

    war.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml"); 
    war.setWebXML(new File("src/main/webapp/WEB-INF/web.xml")); 

    ear.setApplicationXML(new File("../testing-ear/src/main/application/META-INF/application.xml")); 
    ear.addAsManifestResource(new File("../testing-ear/src/main/application/META-INF/ibm-application-bnd.xml")); 
    ear.addAsModule(war); 

    return ear; 
} 

Я аутентичность моего тестового пользователя перед каждым тестом, как это:

@Before 
public void setup() throws LoginException, WSSecurityException { 

    // WLP provided classes to authenticate a user. 
    CallbackHandler wscbh = new WSCallbackHandlerImpl("user", "password"); 
    LoginContext ctx = new LoginContext("WSLogin", wscbh); 
    ctx.login(); 

    // Set the user as the current user on the thread. 
    Subject mySubject = ctx.getSubject(); 
    WSSubject.setRunAsSubject(mySubject); 

} 

Тогда в тест, я проверяю, чтобы увидеть, если имя пользователя является недействительным, как это:

@Test 
public void testAuthenticatedPrincipal() throws LoginException, WSSecurityException { 


    assertNull("User name should not be null.", manager.getCurrentUserName()); 
} 

выполнение этого теста всегда приводит к NPE с трассировки стека:

java.lang.NullPointerException 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:95) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:56) 
at java.lang.reflect.Method.invoke(Method.java:620) 
at org.apache.webbeans.component.BuildInOwbBean$BuildInBeanMethodHandler.invoke(BuildInOwbBean.java:273) 
at org.apache.webbeans.component.BuildInOwbBean$BuildInBeanMethodHandler.invoke(BuildInOwbBean.java:267) 
at org.javassist.tmp.java.lang.Object_$$_javassist_2.getName(Object_$$_javassist_2.java) 
at com.testing.cdi.CdiUserManager.getCurrentUserName(CdiUserManager.java:23) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:95) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:56) 
at java.lang.reflect.Method.invoke(Method.java:620) 
at org.apache.webbeans.intercept.InterceptorHandler.invoke(InterceptorHandler.java:327) 
at org.apache.webbeans.intercept.NormalScopedBeanInterceptorHandler.invoke(NormalScopedBeanInterceptorHandler.java:117) 
at org.apache.webbeans.intercept.NormalScopedBeanInterceptorHandler.invoke(NormalScopedBeanInterceptorHandler.java:108) 
at com.testing.cdi.CdiUserManager_$$_javassist_1.getCurrentUserName(CdiUserManager_$$_javassist_1.java) 
at com.testing.cdi.test.UserManagerTest.testAuthenticatedPrincipal(UserManagerTest.java:85) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:95) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:56) 
at java.lang.reflect.Method.invoke(Method.java:620) 
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.jboss.arquillian.junit.Arquillian$6$1.invoke(Arquillian.java:325) 
at org.jboss.arquillian.container.test.impl.execution.LocalTestExecuter.execute(LocalTestExecuter.java:60) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:95) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:56) 
at java.lang.reflect.Method.invoke(Method.java:620) 
at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:94) 
at org.jboss.arquillian.core.impl.EventContextImpl.invokeObservers(EventContextImpl.java:99) 
at org.jboss.arquillian.core.impl.EventContextImpl.proceed(EventContextImpl.java:81) 
at org.jboss.arquillian.core.impl.ManagerImpl.fire(ManagerImpl.java:145) 
at org.jboss.arquillian.core.impl.ManagerImpl.fire(ManagerImpl.java:116) 
at org.jboss.arquillian.core.impl.EventImpl.fire(EventImpl.java:67) 
at org.jboss.arquillian.container.test.impl.execution.ContainerTestExecuter.execute(ContainerTestExecuter.java:38) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:95) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:56) 
at java.lang.reflect.Method.invoke(Method.java:620) 
at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:94) 
at org.jboss.arquillian.core.impl.EventContextImpl.invokeObservers(EventContextImpl.java:99) 
at org.jboss.arquillian.core.impl.EventContextImpl.proceed(EventContextImpl.java:81) 
at org.jboss.arquillian.test.impl.TestContextHandler.createTestContext(TestContextHandler.java:102) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:95) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:56) 
at java.lang.reflect.Method.invoke(Method.java:620) 
at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:94) 
at org.jboss.arquillian.core.impl.EventContextImpl.proceed(EventContextImpl.java:88) 
at org.jboss.arquillian.test.impl.TestContextHandler.createClassContext(TestContextHandler.java:84) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:95) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:56) 
at java.lang.reflect.Method.invoke(Method.java:620) 
at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:94) 
at org.jboss.arquillian.core.impl.EventContextImpl.proceed(EventContextImpl.java:88) 
at org.jboss.arquillian.test.impl.TestContextHandler.createSuiteContext(TestContextHandler.java:65) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:95) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:56) 
at java.lang.reflect.Method.invoke(Method.java:620) 
at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:94) 
at org.jboss.arquillian.core.impl.EventContextImpl.proceed(EventContextImpl.java:88) 
at org.jboss.arquillian.core.impl.ManagerImpl.fire(ManagerImpl.java:145) 
at org.jboss.arquillian.test.impl.EventTestRunnerAdaptor.test(EventTestRunnerAdaptor.java:135) 
at org.jboss.arquillian.junit.Arquillian$6.evaluate(Arquillian.java:318) 
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) 
at org.jboss.arquillian.junit.Arquillian$5.evaluate(Arquillian.java:277) 
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) 
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) 
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) 
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.jboss.arquillian.junit.Arquillian$2.evaluate(Arquillian.java:202) 
at org.jboss.arquillian.junit.Arquillian.multiExecute(Arquillian.java:377) 
at org.jboss.arquillian.junit.Arquillian.access$200(Arquillian.java:52) 
at org.jboss.arquillian.junit.Arquillian$3.evaluate(Arquillian.java:216) 
at org.junit.runners.ParentRunner.run(ParentRunner.java:309) 
at org.jboss.arquillian.junit.Arquillian.run(Arquillian.java:164) 
at org.junit.runner.JUnitCore.run(JUnitCore.java:160) 
at org.junit.runner.JUnitCore.run(JUnitCore.java:138) 
at org.jboss.arquillian.junit.container.JUnitTestRunner.execute(JUnitTestRunner.java:66) 
at org.jboss.arquillian.protocol.servlet.runner.ServletTestRunner.executeTest(ServletTestRunner.java:159) 
at org.jboss.arquillian.protocol.servlet.runner.ServletTestRunner.execute(ServletTestRunner.java:125) 
at org.jboss.arquillian.protocol.servlet.runner.ServletTestRunner.doGet(ServletTestRunner.java:89) 
at javax.servlet.http.HttpServlet.service(HttpServlet.java:575) 
at javax.servlet.http.HttpServlet.service(HttpServlet.java:668) 
at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1285) 
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:776) 
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:473) 
at com.ibm.ws.webcontainer.filter.WebAppFilterManager.invokeFilters(WebAppFilterManager.java:1104) 
at com.ibm.ws.webcontainer.webapp.WebApp.handleRequest(WebApp.java:4845) 
at com.ibm.ws.webcontainer.osgi.DynamicVirtualHost$2.handleRequest(DynamicVirtualHost.java:297) 
at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:981) 
at com.ibm.ws.webcontainer.osgi.DynamicVirtualHost$2.run(DynamicVirtualHost.java:262) 
at com.ibm.ws.http.dispatcher.internal.channel.HttpDispatcherLink$TaskWrapper.run(HttpDispatcherLink.java:955) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1157) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:627) 
at java.lang.Thread.run(Thread.java:863) 

В прошлом я разработал проекты EJB и интеграцию с ними, используя этот метод. Инъекционный SessionContext заменяет Принципала в этом сценарии. Кто-нибудь имеет какие-либо советы или опыт о том, как запустить этот тест?

P.S. Я использую IBM JDK v1.7.1 с WebSphere Liberty Developer Edition v8.5.5.5.

ответ

0

Обычно нулевое значение используется для принципала пользователя, который не зарегистрирован, например. HttpServletRequest.getUserPrincipal() возвращает значение null, если пользователь не прошел аутентификацию.

Поэтому я не считаю, что вводимый Принципал не имеет значения. Тем не менее, Принципал также является компонентом CDI, который проксирован. Поскольку у вас есть внедренный прокси-объект, вы не можете проверить его на nullness, но при вызове getName() CDI пытается найти настоящего Принципала для зарегистрированного пользователя и вызывает getName() на нем, в результате чего возникает исключение NullPointerException.

Я понимаю, что это не очень полезно, поскольку вы не можете использовать основной компонент для проверки подлинности пользователя, но я не думаю, что это неправильно.

Для теста Arquillian вы можете выполнить тестовый запуск как клиент, а не на сервере, чтобы вы могли вручную вызвать URL сервлета и предоставить учетные данные для проверки подлинности. Вам нужно, чтобы сервлет распечатал имя пользователя и убедитесь, что на клиенте правильный ответ.

Ниже приведена информация о выполнении тестов в режиме клиента: https://docs.jboss.org/author/display/ARQ/Test+run+modes

Смежные вопросы