首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

精通 Grails 创建自定义插件(3)

精通 Grails 创建自定义插件(3)

创建 ShortenUrl 服务要创建一个服务,输入 grails create-service ShortenUrl。将清单 9 中的代码添加到 grails-app/services/ShortenUrlService.groovy。
清单 9. ShortenUrl 服务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import org.grails.shortenurl.*

class ShortenUrlService {
    boolean transactional = false

    def tinyurl(String longUrl) {
      return TinyUrl.shorten(longUrl)
    }

    def isgd(String longUrl) {
      def shortUrl = IsGd.shorten(longUrl)
      if(shortUrl.contains("error")){
        log.error(shortUrl)
      }
      return shortUrl
    }
}




与前面的集成测试相似,确保将 transactional 标记设置为 false。这些调用不涉及任何数据库,所以不必将它们封装到一个事务中。
注意,isgd() 方法将记录任何企图缩短一个无效 URL 的日志。所有 Grails 工件将在运行时使用一个 log 对象注入。可以调用 log 对象上与想要的日志级别相对应的方法,这些日志级别包括: debug、info 和 error 等(参见  了解关于日志记录的更多信息)。您稍后将会看到,编写单元测试时,处理这个注入的 log 对象需要一个额外步骤。
当 Grails 为您创建服务时,它将把相应的测试添加到 test/unit 目录。通常,您需要将 ShortenUrlServiceTests.groovy 移动到 test/integration 目录,因为在语义上,它是一个集成测试,而不是一个单元测试 — 依赖外部资源测试服务。但现在,您应将它保留在 test/unit 目录中,以便我能够向您展示几个单元测试技巧。将清单 10 中的代码添加到 ShortenUrlServiceTests.groovy。
清单 10. 测试 ShortenUrl 服务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import grails.test.*

class ShortenUrlServiceTests extends GrailsUnitTestCase {
    def transactional = false
    def shortenUrlService
   
    protected void setUp() {
        super.setUp()
        shortenUrlService = new ShortenUrlService()
    }

    protected void tearDown() {
        super.tearDown()
    }

    void testTinyUrl() {
      def shortUrl = shortenUrlService.tinyurl("http://grails.org")
      assertEquals "http://tinyurl.com/3xfpkv", shortUrl
    }

    void testIsGd() {
      def shortUrl = shortenUrlService.isgd("http://grails.org")
      assertEquals "http://is.gd/2oCZR", shortUrl        
    }

    void testIsGdWithBadUrl() {
      def shortUrl = shortenUrlService.isgd("IAmNotAValidUrl")
      assertTrue shortUrl.startsWith("An error occurred:")
    }
}




注意,将 transactional 标志设置为 false 后,我们声明了 shortenUrlService 变量。然后在 setUp() 方法中初始化服务。为每个服务调用 setUp() 和 tearDown() 方法。
如果这是一个集成测试,则不会出现错误。但由于这是一个单元测试,testIsGdWithBadUrl() 方法失败并显示错误消息:No such property: log for class: ShortenUrlService。在 Web 浏览器中打开 test/reports/html/index.html,您将看到如图 2 所示的错误消息。
图 2. 注入的 log 对象导致单元测试失败如上所示,log 对象并没有注入服务中以进行单元测试。(记住:单元测试意味着完全隔离运行)。好在解决这个问题只需在 setUp() 方法中添加一行 —mockLogging(ShortenUrlService) — 如清单 11 所示。
清单 11. 模拟注入的 log 对象
1
2
3
4
5
protected void setUp() {
    super.setUp()
    mockLogging(ShortenUrlService)
    shortenUrlService = new ShortenUrlService()
}




mockLogging() 方法将一个模拟 log 对象注入到服务中。这个模拟记录器将它的输出发送到 System.out 而不是任何已定义的 log4j 输出器。要查看输出(如图 3 所示),再次输入 grails test-app,单击 ShortenUrlServiceTests 的 HTML 报告页面底部的 System.out 链接。
图 3. 模拟记录器的输出您还可以为这个插件集成大量其他 Grails 工件 — 一个自定义 TagLib 以缩短 GSP 中的 URL,一个自定义编解码器 — 但现在您已经充分了解一个插件可以提供的内容,在这里就不一一演示了。在下一个小节中,我们将把这个插件原样打包并集成到另一个 Grails 项目中。
返回列表