如何使用 TestNG 和一些 Mocking 框架来模拟 HTTPSession/FlexSession
我正在开发一个在 Tomcat 6 上运行的 Web 应用程序,以 Flex 作为前端。我正在使用 TestNG 测试我的后端。目前,我正在尝试在 Java 后端中测试以下方法:
public class UserDAO extends AbstractDAO {
(...)
public UserPE login(String mail, String password) {
UserPE dbuser = findUserByMail(mail);
if (dbuser == null || !dbuser.getPassword().equals(password))
throw new RuntimeException("Invalid username and/or password");
// Save logged in user
FlexSession session = FlexContext.getFlexSession();
session.setAttribute("user", dbuser);
return dbuser;
}
}
该方法需要访问 FlexContext,该方法仅当我在 Servlet 容器上运行它时才存在(如果您不了解 Flex,请不要打扰,它更重要)一般是 Java 模拟问题)。否则,在调用 session.setAttribute()
时,我会收到 Nullpointer 异常。 不幸的是,我无法从外部设置 FlexContext,这将使我能够从测试中设置它。它只是在方法内部获得的。
在不更改方法或包含该方法的类的情况下,使用 Mocking 框架测试此方法的最佳方法是什么?对于这个用例来说,哪个框架是最简单的(我的应用程序中几乎没有其他东西需要模拟,这非常简单)?
抱歉,我可以自己尝试所有这些,看看如何让它发挥作用,但我希望我能得到一些好的建议来快速入门!
I'm developing a web application running on Tomcat 6, with Flex as Frontend. I'm testing my backend with TestNG. Currently, I'm trying to test the following method in my Java-Backend:
public class UserDAO extends AbstractDAO {
(...)
public UserPE login(String mail, String password) {
UserPE dbuser = findUserByMail(mail);
if (dbuser == null || !dbuser.getPassword().equals(password))
throw new RuntimeException("Invalid username and/or password");
// Save logged in user
FlexSession session = FlexContext.getFlexSession();
session.setAttribute("user", dbuser);
return dbuser;
}
}
The method needs access to the FlexContext which only exists when i run it on the Servlet container (don't bother if you don't know Flex, it's more a Java-Mocking question in general). Otherwise i get a Nullpointer exception when calling session.setAttribute()
.
Unfortunately, I cannot set the FlexContext from outside, which would make me able to set it from my tests. It's just obtained inside the method.
What would be the best way to test this method with a Mocking framework, without changing the method or the class which includes the method? And which framework would be the easiest for this use case (there are hardly other things i have to mock in my app, it's pretty simple)?
Sorry I could try out all of them for myself and see how i could get this to work, but i hope that i'll get a quickstart with some good advices!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
显而易见的一种方法是以一种允许您注入 FlexContext 等内容的方式对其进行重构。然而这并不总是可能的。不久前,我所在的一个团队遇到了一种情况,我们必须模拟一些我们无法访问的内部类内容(例如您的上下文)。我们最终使用了一个名为 jmockit 的 api,它允许您有效地模拟单个方法,包括静态调用。
使用这项技术,我们能够绕过非常混乱的服务器实现,而不必部署到实时服务器和黑盒测试,我们能够通过覆盖有效硬编码的服务器技术来进行精细的单元测试。
关于使用 jmockit 之类的东西,我唯一的建议是确保在您的测试代码中有清晰的文档,并将 jmockit 与主模拟框架分开(easymock 或 mockito 是我的推荐)。否则,您可能会让开发人员对难题的每个部分的各种职责感到困惑,这通常会导致测试质量差或测试效果不佳。理想情况下,正如我们最终所做的那样,将 jmockit 代码包装到您的测试装置中,这样开发人员甚至不知道它。对于大多数人来说,处理 1 个 api 就足够了。
顺便说一句,这是我们用来修复 IBM 类测试的代码。我们基本上需要做两件事,
这是代码:
这是我们用作测试父级的抽象类。
Obvious one approach is to re-factor it in a way that lets you inject things like the FlexContext. However this is not always possible. Some time ago a team I was part of hit a situation where we had to mock out some internal class stuff that we didn't have access to (like your context). We ended up using an api called jmockit which allows you to effective mock individual methods, including static calls.
Using this technology we where able to get around a very messy server implementation and rather than having to deploy to live servers and black box test, we were able to unit test at a fine level by overriding the server technology that was effective hard coded.
The only recommendation I would make about using something like jmockit is to ensure that in your test code there is clear documentation and seperation of jomockit from you main mocking framework (easymock or mockito would be my recommendations). Otherwise you risk confusing developers about the various responsibilities of each part of the puzzle, which usually leads to poor quality tests or tests that don't work that well. Ideally, as we ended up doing, wrap the jmockit code into you testing fixtures so the developers don't even know about it. Dealing with 1 api is enough for most people.
Just for the hell of it, here's the code we used to fix testing for an IBM class. WE basically need to do two things,
Here's the code:
And here's the abstract class we used as a parent for tests.
感谢 Derek Clarkson,我成功模拟了 FlexContext,使登录可测试。不幸的是,据我所知,只有 JUnit 才可能实现(测试了 TestNG 的所有版本均未成功 - JMockit javaagent 不喜欢 TestNG,请参阅 此 和 这个问题)。
这就是我现在正在做的事情:
为了进一步测试,我现在必须自己实现会话映射之类的东西。但这没关系,因为我的应用程序和我的测试用例非常简单。
Thanks to Derek Clarkson, I successfully mocked the FlexContext, making the login testable. Unfortunately, it's only possible with JUnit, as far as i see (tested all versions of TestNG with no success - the JMockit javaagent does not like TestNG, See this and this issues).
So this is how i'm doing it now:
For further testing i now have to implement things like the session map myself. But thats okay as my app and my test cases are pretty simple.