4

我有一个 cfc,它的许多核心功能严重依赖于 Java 对象(通过 JavaLoader 创建),我想为其编写一些测试,但我不确定最好的方法是什么。这是我想为 instance.note 作为 java 对象编写测试的方法示例。

<cffunction name="getNotes" returntype="Array" access="public" output="false" hint="I return a list of a users notebooks" >
    <cfargument name="maxCount" type="numeric" required="false" default="9999" hint="The maximum number of notes to get" />
    <cfscript>
        if(arguments.maxCount)
            return instance.note.listNotes(maxCount);
        else
            return instance.note.listNotes();
    </cfscript>
</cffunction>

我想做的一件事是创建一个具有相同方法名称和相似返回值的存根 CFC,然后模拟该存根并注入它?

4

3 回答 3

3

你不能只在结果上写有意义的断言,即在笔记数组上吗?查看该代码,我唯一要测试的是 a) 当您通过 maxCount 时,您的结果数组是否符合该大小?b) 如果没有 maxCount,音符列表的长度是否符合您的预期?因为这就是你的代码所做的一切。我会测试你的代码,而不是底层 java 对象的代码。

于 2011-07-14T12:26:38.730 回答
2

当我们需要对依赖于 Java 对象(我们做了很多)的 CF 函数进行单元测试时,我们使用Mockito来模拟 Java 对象。

所以,希望这个代码片段有意义,自从我这样做已经快一年了:

<cfcomponent displayname="TestWhatever" extends="mxunit.framework.TestCase" output="false">

    <cffunction name="setUp" access="public" returntype="void">
      <cfscript>
        // named it mk for keeping it short
        variables.mk = createObject("java","org.mockito.Mockito");

        //Create the mock object
        variables.mockNote = mk.mock(createObject("java","com.company.whatever.note").getClass());

        // Mock Data
        fullList = {whatever listNotes() returns}
        partialList3 = {whatever listNotes(3) returns}

        //some common mocking
        mk.when(variables.mockNote.listNotes()).thenReturn(fullList);
        mk.when(variables.mockNote.listNotes(mk.eq(3))).thenReturn(partialList3);
        mk.when(variables.rootOrgObj.guid()).thenReturn("root");

        // Assign the mock object to where your CFC expects it.
        instance.note = variables.mockNote
      </cfscript>
    </cffunction>

</cfcomponent>

话虽如此,如果您的示例函数是真实的,那么对它进行单元测试真的没有意义。它根本不做任何事情,只是作为 java 对象的代理。那里没有重要的逻辑可以测试。

由于您在 cfargument 上有一个默认值,因此它将始终存在(我认为是这样,自从我完成 CF 以来已经有一年了),因此您甚至不需要您的保护语句 - 将始终调用第一个代码路径,如果指定,则使用传递的 maxCount,否则使用 9999。

于 2011-07-14T20:47:14.687 回答
0

我接受了爱德华的回答并像这样实施它:

我使用 JavaLoader 库来创建我的 mockito 对象。变量.cfEvernote = "";

variables.classLoader = createObject("component", "resources.JavaLoader").
    init(["#expandPath('../lib/mockito-all-1.8.5.jar')#",
          "#expandPath('../lib/CFEvernote.jar')#",                                                                      
          "#expandPath('../lib/libthrift.jar')#",
          "#expandPath('../lib/evernote-api-1.18.jar')#"]);  

variables.mockito = variables.classLoader.create("org.mockito.Mockito").init();

然后在我的 munit 测试的 setup 方法中,我创建了新的模拟 java 对象:

<cffunction name="setUp" access="public" output="false" returntype="void">
<cfscript>
variables.cfEvernote = createObject("component","com.714studios.cfevernote.CFEvernote").
                        Init(variables.configArray[1],variables.configArray[2],
                             "sandbox.evernote.com",
                             "http://localhost/cfevernote/callback.cfm"
                             "#ExpandPath('../lib')#");

variables.mockCFEvernote = variables.mockito.mock(variables.classLoader.create("com.sudios714.cfevernote.CFEvernote").
                           Init("123","S1","232","sandbox.evernote.com","mock").getClass());

variables.cfEvernote.setCFEvernote(mockCFEvernote);
</cfscript>     

然后在我的测试中,我像这样创建我的模拟行为。

<cffunction name="test..."  returntype="void" access="public" output="false" >
<cfscript>
    var notebooks = ""; 
    var expected = 12;
    var i = 0;
    var retArray = createObject("Java","java.util.ArrayList");
    var actual = "";

    for(i = 1; i lte 12; i = i + 1){
        retArray.Add("");
    }

    variables.mockito.when(mockCFEvernote.listNotebooks(12)).thenReturn(retArray);

    notebooks = variables.cfEvernote.getNotebooks(12); 

    actual = arrayLen(notebooks);

    assertEquals(expected,actual);
</cfscript>

我还在这里更详细地写了一篇博客 - http://blog.bittersweetryan.com/2011/07/unit-testing-coldfusion-components-that.html

于 2011-07-19T12:25:20.133 回答