【问题标题】:ServletContextListener attribute set in event is null事件中设置的 ServletContextListener 属性为 null
【发布时间】:2017-08-11 19:14:58
【问题描述】:

我有一个像下面这样的 ServletContextListener

public class MyServletContextListener implements ServletContextListener {

@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
    System.out.println("Start");
    servletContextEvent.getServletContext().setAttribute("id1", "this is my value");
    System.out.println("Current value is" + servletContextEvent.getServletContext().getAttribute("id1"));
    System.out.println("End");
}

这将打印:

Start
Current value is null
End

是的,监听器是在web.xml中定义的:

<listener>
    <listener-class>package.path.MyServletContextListener</listener-class>
</listener>

我错过了什么?

乐: 我在我的单元测试中获得了这个(使用junit和mockito)。在我的 TestClass 中,我有一个 @BeforeClass 方法,我在其中执行以下操作:

ServletRunner sr = new ServletRunner(new File("src/test/resources/WEB-INF/web.xml"));
ServletUnitClient sc = sr.newClient();

listener = new MyServletContextListener ();

    event = mock(ServletContextEvent.class);
    servletContext = mock(ServletContext.class);

    when(event.getServletContext()).thenReturn(servletContext);

    listener.contextInitialized(event);

【问题讨论】:

  • 很好奇。我倾向于怀疑您提供的示例并不代表问题首次出现的真实代码 - 您没有使用相同的键来检索您用来设置它的值,或者也许您正在回读null,因为这是您实际设置的值。您真的可以通过您提供的确切代码产生您描述的行为吗?
  • 是的,你是对的。这只是一个产生相同结果的示例代码。是的,为此类运行 junit 测试会产生上述输出。这就是为什么我认为我错过了一些东西。我正在使用相同的密钥来检索它,它是一个常量。
  • 在单元测试期间观察到这种行为的事实改变了一切。在这种情况下,它与正在测试的内容高度相关——我想可能是你的听众的contextInitialized() 方法——以及如何设置测试夹具来模拟执行环境。您观察到的行为的出现完全有可能是因为测试夹具没有充分模拟 servlet 容器。例如,它的ServletContextEvent.getContext() 实现可能会在每次调用时返回一个新对象。
  • 查看更新的问题。

标签: java web.xml servletcontextlistener


【解决方案1】:

问题似乎出在您的 ServletContext 模拟中。您通过Mockito.mock(ServletContext.class) 创建它,而Mockito 足够聪明,可以提供一个实现所有ServletContext 方法的对象,但是您认为它如何知道要实现什么行为

它本身不能,不仅仅是接口类继续。 Mockito 所能做的就是为存根提供正确的签名。您没有做任何事情(在您呈现的内容中)来提供模拟的 setAttribute() 方法来实际记录设置的属性,或者它的 getAttribute() 方法来查找并返回该对象。 Mockito 可以支持这一点,看起来,但你需要告诉它该做什么。

还要注意,如果要验证contextInitialized() 方法是否设置了属性,那么最好的检查方法是检测ServletContext 模拟,而不是通过观察侦听器对System.out 的输出。依赖输出也将其纳入测试范围,因此现在您正在联合测试两个不同的功能。

【讨论】:

  • 这是一般问题,我对此的实际解决方案是模拟它:when(servletContext.getAttribute(anyString())) .thenReturn("my value");
猜你喜欢
  • 1970-01-01
  • 2018-09-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-26
相关资源
最近更新 更多