3

与此问题相关: Uncaught TypeError: Cannot use 'in' operator to search for 'SUPPORT_COOKIES' in null

但由于 Jasmine 测试工具和关于 JS-Java 适配器测试的最佳实践的一般问题而有所不同。


我们正在努力为一组开发人员建立一个开发环境,包括持续集成、构建和自动化测试。

为此,我们需要有一种方法从独立于实际 Worklight 应用程序或任何 Worklight 客户端运行的独立测试用例/客户端(测试代码)调用 WL 服务器上的 WL 适配器。这些测试必须在部署和持续构建时运行,并将测试适配器。

我们提出了这个解决方案,因为在部署适配器之前无法在本地测试适配器。此外,我们不能真正将测试代码包含到我们的适配器中并将代码与适配器一起部署。这不是一个好的解决方案,我们将在带有适配器的服务器上测试代码。

我们可能会使用JasmineJUnit作为我们的测试工具,我尝试通过包含所有 Worklight JS 库和变量(worklight 编译器添加到最终编译和部署的 App .html)来设置独立的 Jasmine Worklight Client/Test我的茉莉花测试。

它运行了一段时间,似乎初始化正常:

wlclient init started worklight.js:1112
before: app init onSuccess worklight.js:1112
after: app init onSuccess worklight.js:1112
wlclient init success

但是当我想执行 WL.Client.invokeProcedure(invocationData, 我得到错误:

TypeError:无法使用“in”运算符在 null 中搜索“SUPPORT_COOKIES”

因此,我的独立 Worklight 客户端/测试中似乎缺少一些配置或初始化。有哪位专家能告诉我那可能是什么吗?

<head>
    <title>Jasmine Spec Runner</title>
 <link rel="stylesheet" type="text/css" href="lib/jasmine-1.3.1/jasmine.css">

<script>
        // Define WL namespace.
        var WL = WL ? WL : {};

        /**
         * WLClient configuration variables.
         * Values are injected by the deployer that packs the gadget.
         */


        WL.StaticAppProps = {
         "APP_DISPLAY_NAME": "app",
   "APP_SERVICES_URL": "\/tests\/",
   "APP_VERSION": "1.0",
   "ENVIRONMENT": "preview",
   "HEIGHT": 460,
   "LOGIN_DISPLAY_TYPE": "popup",
   "LOGIN_POPUP_HEIGHT": 610,
   "LOGIN_POPUP_WIDTH": 920,
   "PREVIEW_ENVIRONMENT": "common",
   "WIDTH": 320,
       "WORKLIGHT_ROOT_URL": "\/tests\/"
    };



<script src="lib/common/js/wljq.js"></script>
        <script src="lib/common/js/base.js"></script>
        <script src="lib/common/js/containerCommunicationAPI.js"></script>
        <script src="lib/wlclient/js/messages.js"></script>
        <script src="lib/common/js/wlcommon.js"></script>
        <script src="lib/common/js/busy.js"></script>
        <script src="lib/wlclient/js/diagnosticDialog.js"></script>
        <script src="lib/wlclient/js/deviceAuthentication.js"></script>
        <script src="lib/wlclient/js/window.js"></script>
        <script src="lib/wlclient/js/worklight.js"></script>
        <script src="lib/wlclient/js/gadgetCommunicationAPI.js"></script>
        <script src="lib/wlclient/js/wlclient.js"></script>
        <script src="lib/wlclient/js/wlfragments.js"></script>
        <script src="lib/wlclient/js/encryptedcache.js"></script>
        <script src="lib/wlclient/js/jsonstore/jsonstore.js"></script>
        <script src="lib/wlclient/js/challengeHandlers/antiXSRFChallengeHandler.js"></script>
        <script src="lib/wlclient/js/challengeHandlers/authenticityChallengeHandler.js"></script>
        <script src="lib/wlclient/js/challengeHandlers/deviceAuthAutoProvisioningChallengeHandler.js"></script>
        <script src="lib/wlclient/js/challengeHandlers/deviceAuthNoProvisioningChallengeHandler.js"></script>
        <script src="lib/wlclient/js/challengeHandlers/remoteDisableChallengeHandler.js"></script>
            <script src="../apps/app/common/js/jquery-1.10.1.min.js"></script>
    <!-- script>window.$ = window.jQuery = WLJQ;</script-->
    <script src="../apps/app/common/jqueryMobile/jquery.mobile-1.3.1.js"></script>

    <script src="../apps/app/common/js/initOptions.js"></script>
     <script src="../apps/app/common/js/messages.js"></script>


    <script type="text/javascript" src="lib/jasmine-1.3.1/jasmine.js"></script>
    <script type="text/javascript" src="lib/jasmine-1.3.1/jasmine-html.js"></script>

    <!-- include source files here... -->

    <!--<script type="text/javascript" src="../apps/app/common/js/knockout-2.2.1.js"></script>-->
    <!--<script type="text/javascript" src="../apps/app/common/js/knockout.mapping-latest.js"></script>-->
    <!--<script type="text/javascript" src="../apps/app/common/js/globalize.js"></script>-->
    <!--<script type="text/javascript" src="../apps/app/common/js/app.js"></script> -->
    <!--<script type="text/javascript" src="../apps/app/common/js/common.js"></script>-->
    <!--<script type="text/javascript" src="../apps/app/common/js/date.js"></script>-->
    <!--<script type="text/javascript" src="../apps/app/common/js/localize.js"></script>-->
    </script>-->


    <!-- include spec files here... -->
    <!--script type="text/javascript" src="spec/SpecHelper.js"></script-->
    <script type="text/javascript" src="spec/TestSpec.js"></script>

2013 年 7 月 15 日:

以这种方式让 Jasmine 在 WL 客户端中自动运行:

var wlInitOptions = {

    connectOnStartup : false,

};

if (window.addEventListener) {
    window.addEventListener('load', function() { WL.Client.init(wlInitOptions); execJasmine(); }, false);
} else if (window.attachEvent) {
    window.attachEvent('onload',  function() { WL.Client.init(wlInitOptions); execJasmine(); });
}

function wlCommonInit(){


}

var jasmineEnv = jasmine.getEnv();
jasmineEnv.updateInterval = 1000;

var htmlReporter = new jasmine.HtmlReporter();

jasmineEnv.addReporter(htmlReporter);

jasmineEnv.specFilter = function(spec) {
    return htmlReporter.specFilter(spec);
};

function execJasmine() {
    WL.Logger.debug("ExecJasmine");
    jasmineEnv.execute();
}

但是现在我遇到了访问控制问题,因为我的 WL-Jasmine-Test-Client在端口 80 上的 Apache和端口 8080上的 WL 服务器上的适配器上运行。

running test worklight.js:1112
Application did not define an i18n messages object, skipping translation. worklight.js:1112
wlclient init started worklight.js:1112
before: app init onSuccess worklight.js:1112
after: app init onSuccess worklight.js:1112
wlclient init success worklight.js:1112
ExecJasmine worklight.js:1112
Request [http://XXX:8080/apps/services/api/app/desktopbrowser/query] worklight.js:1112
running test 2 worklight.js:1112
OPTIONS http://XXX:8080/apps/services/api/app/desktopbrowser/query 401 (Unauthorized) base.js:883
OPTIONS http://XXX:8080/apps/services/api/app/desktopbrowser/query Origin http://XXX is not allowed by Access-Control-Allow-Origin. base.js:883
XMLHttpRequest cannot load http://XXX:8080/apps/services/api/app/desktopbrowser/query. Origin http://XXX is not allowed by Access-Control-Allow-Origin. SpecRunnerAdapter.html:1
Refused to get unsafe header "X-JSON" base.js:994
[http://XXX:8080/apps/services/api/app/desktopbrowser/query] Host is not responsive. worklight.js:1112
{"invocationContext":null,"errorCode":"UNRESPONSIVE_HOST","errorMsg":"The service is currently not available."} worklight.js:1112
Refused to get unsafe header "X-JSON" 

使用此 WL-Test-Client 应用程序配置:

        WL.StaticAppProps = {
   "APP_DISPLAY_NAME": "app",
   "APP_SERVICES_URL": "http:\/\/XXX:8080\/apps\/services\/",
   "APP_VERSION": "1.0",
   "ENVIRONMENT": "desktopbrowser",
   "HEIGHT": 460,
   "LOGIN_DISPLAY_TYPE": "popup",
   "LOGIN_POPUP_HEIGHT": 610,
   "LOGIN_POPUP_WIDTH": 920,
   "WIDTH": 320,
   "WORKLIGHT_ROOT_URL": "http:\/\/XXX:8080\/apps\/services\/api\/app\/desktopbrowser\/"
};

我想我们会在这里停下来,简单地使用 WL-Server 上的 INVOKE 服务来调用wl_unprotected Adapter Procedures以在测试环境中进行 JUnit 测试。

然后弄清楚如何在构建/部署时保护生产过程,同时删除单元测试执行——因为它们不再与受保护的适配器一起使用。

4

2 回答 2

1

对于单元测试,您最好的选择是使用 WL 适配器调用服务。根本没有客户端代码,只需向 WL 服务器发出 HTTP(s) 请求:

http://pic.dhe.ibm.com/infocenter/wrklight/v6r0m0/index.jsp?topic=%2Fcom.ibm.worklight.help.doc%2Fdevref%2Fc_adapter_invocation_service.html

于 2013-07-13T07:25:41.460 回答
1

假设您想要对适配器代码进行单元测试,例如指定问题的标题,我会注意以下几点:

  • 单元测试的范围是单个代码单元,在 JavaScript 中通常意味着一个小函数。您测试是否sum(1,2)返回3。您不会自动打开显示计算器应用程序的 URL,模拟用户输入以单击按钮(12=,等待计算事件返回3并且测试代码从 DOM 读取输出。前者描述了单元测试,后者描述了集成/功能测试。如果您想要功能测试,请阅读。如果您想要单元测试,请继续阅读。

  • 模拟与第三方 API 相关的所有内容(例如 Worklight、jQuery、Dojo)。这些 API 已经过测试并且已知可以工作,至少这是一个合理的假设。例如,当您编写 JUnit 测试时,您假设标准 Java 库中的所有内容都按照文档中指定的方式工作。Sinon.js是一个很棒的库,用于创建 JavaScript 模拟、存根和间谍。

  • 使用Mozilla RhinoNode.js来读取和评估适配器的 JavaScript 实现文件的 JavaScript(例如myCalculatorAdapter-impl.js)。有许多创建断言的好方法,例如Mocha,如果您使用 Node.js 路线。

这是一些示例代码,想象一下这是我的适配器程序:

myCalculatorAdapter-impl.js

function sum (a, b) {
    WL.Logger.debug({hello: 'world'});
    return a+b;
}

想象一下以下包含我对所述适配器过程的单元测试:

测试.js

//Mocks
var WL = {};
WL.Logger = {};
WL.Logger.debug = function (msg) {
    console.log(msg);
};

//Node.js Libraries
var fs = require('fs'),
    assert = require('assert');

//Read the adapter code
eval(fs.readFileSync('./myCalculatorAdapter-impl.js').toString());

//Do assertions -- Unit testing
assert.equal(sum(1, 2), 3, '1+2 should be 3');

我运行它:node test.js。如果我在运行时将实现更改为减法而不是加法(return a-b),我会收到失败警报AssertionError: 1+2 should be 3

我使用了Node.js 提供的标准断言库,您可能想要使用具有更多功能的东西。同样,您可能希望使用库来模拟第三方 API 或不适用于当前测试的东西。如果您正在进行网络通信,您将需要模拟输入。

当然还有其他方法可以测试适配器,请随意尝试和分享。

于 2013-07-13T22:41:34.837 回答