JUnit Liferay服务 [英] JUnit Liferay services

查看:64
本文介绍了JUnit Liferay服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在项目中使用liferay服务生成器,现在我想测试* Util类.这很容易,但是我不知道初始化环境的简单方法. 例如,在从service.xml(自动生成)使用弹簧配置进行蚂蚁测试中,我将InitUtil.initWithSpring()用于初始化bean,但会出现以下错误:

I use liferay service builder in my project and now i want to test *Util classes. It would be easy, but i don't know simple method of init environment. For example in ant testing with spring configuration from service.xml (auto generated) i use InitUtil.initWithSpring() for init beans, but get follow error:

[junit] Tests run: 1, Failures: 0, Errors: 1, Time elapsed: 2,413 sec
[junit] Tests run: 1, Failures: 0, Errors: 1, Time elapsed: 2,413 sec
[junit] 
[junit] Testcase: testJournalArticleSearch(MTest):  Caused an ERROR
[junit] BeanLocator has not been set for servlet context My-portlet
[junit] com.liferay.portal.kernel.bean.BeanLocatorException: BeanLocator has not been set for servlet context My-portlet
[junit]     at com.liferay.portal.kernel.bean.PortletBeanLocatorUtil.locate(PortletBeanLocatorUtil.java:42)
[junit]     at com.my.service.EntityLocalServiceUtil.getService(EntityLocalServiceUtil.java:70)
[junit]     at MTest.setUp(MTest.java:21)

我看过一些有关此问题的文章,但是它不起作用,或者我听不懂这些文章... 有人知道解决这个问题的简单方法吗?

I've seen a few articles on this problem, but it doesn't work or i don't understand these articles... Somebody knows a simple solution to this problem?

推荐答案

我正在写这个作为答案-可能更多是评论,但是我要遵循的是格式化选项和答案的长度.

I'm writing this as an answer - it would be more a comment, but the formatting options and length of an answer are what I'm going after.

我经常看到人们在为生成的代码编写单元测试时遇到麻烦-对我来说* Util和servicebuilder听起来像生成的代码(* LocalServiceUtil).

I frequently see that people have problems writing unit tests for generated code - and *Util, together with servicebuilder, sounds like generated code (*LocalServiceUtil) to me.

我的建议是相当测试您的* LocalServiceImpl代码,并相信代码生成器是正确的(或者相信代码生成器测试将在其中捕获错误,但这不在您的范围之内).毕竟,servicebuilder的* LocalServiceUtil类提供的功能是一种间接寻址,可以查找正确的实现(基于spring配置)并委托给它. * LocalServiceUtil类中没有业务逻辑-这在* LocalServiceImpl类中.

My advice is to rather test your *LocalServiceImpl code and trust that the codegenerator is correct (or trust that the codegenerator tests will catch mistakes in there, but this is outside of your scope). After all, the functionality that servicebuilder's *LocalServiceUtil classes deliver is an indirection that looks up the correct implementation (based on spring configuration) and delegate to it. There's no business logic in *LocalServiceUtil classes - this is in *LocalServiceImpl classes.

下一点是:有时,甚至* Impl类也很难测试,因为它们可以连接到其他服务,因此需要对其进行模拟.在这种情况下-为了保持单元测试的可读性和数据库的独立性-我建议测试不涉及其他服务的代码层.要选择我从此答案中窃取的代码,以下是我宁愿对其进行测试的方法,将USLocalService从等式中排除(警告:伪代码,从未见过编译器,我正在此输入字段中进行编辑)

The next point is: Sometimes even the *Impl-classes are hard to test, because they reach out to other services, which would need to be mocked. In this case - to keep the unit tests readable and independent of the database - I'm proposing to test a layer of code that doesn't reach out to other services. To pick on the code I stole from this answer, here's how I'd rather test it, excluding UserLocalService from the equation (caution: pseudocode, never saw a compiler, I'm editing in this input field)

我们要测试的代码是:

class MyUserUtil {
  public static boolean isUserFullAge(User user)  {
    Date birthday = user.getBirthday();
    long years = (System.currentTimeMillis() - birthday.getTime()) / ((long)365*24*60*60*1000);
    return years >= 18;
  }
}

对此我的测试将排除UserLocalService:

My Test for this would be ruling out UserLocalService:

@Test
public void testIsUserFullAge() throws Exception {
    //setup (having it here for brevity of the code sample)
    SimpleDateFormat format = new SimpleDateFormat("yyyy_MM_dd");
    Date D2000_01_01 = format.parse("2000_01_01");
    Date D1990_06_30 = format.parse("1990_06_30");
    User mockUserThatIsFullAge = mock(User.class);
    when(mockUserThatIsFullAge.getBirthday()).thenReturn(D1990_06_30);
    User mockUserThatIsNotFullAge = mock(User.class);
    when(mockUserThatIsNotFullAge.getBirthday()).thenReturn(D2000_01_01);

    //run
    asertTrue(MyUserUtil.isUserFullAge(mockUserThatIsFullAge));
    asertFalse(MyUserUtil.isUserFullAge(mockUserThatIsNotFullAge));
}

这里的重要部分是:您的代码适用于User对象,而不适用于用户ID.因此,您无需测试查找.如果您也非常想测试查找(例如,更广泛的测试),则将其称为集成测试.但不要抱怨它是否由于某些无关的更改而经常中断.因为现在您的测试失败的原因来自两个不同的原因:查找失败或您的实现不正确.您希望UNIT测试完全出于以下原因之一而失败,例如立即知道测试失败时出了什么问题,而无需开始调试.

The important part here is: Your code works on a User object, not on a user Id. Thus you don't need to test the lookup. If you desperately want to test the lookup as well (e.g. test on a broader scale), call it integration test. But don't complain if it breaks often because of some unrelated changes. Because now the reasons for your test to fail are of two different sources: The lookup fails OR your implementation is incorrect. You want your UNIT test to fail for exactly one of the reasons, e.g. immediately know what went wrong when the test fails, not start debugging.

哦,是的,该测试将在2018年开始失败,在现实生活中,我会测试更多极端情况,例如明天或昨天才18岁的人),但这是一个不同的话题.

Oh, and yes, that test will start to fail in 2018, in real life I'd test more corner cases, e.g. someone who turns 18 tomorrow or did so yesterday), but this is a different topic.

这篇关于JUnit Liferay服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆