Callbacks not working in unit tests?

Former Member
Former Member
Hello, I cannot get callbacks working in unit tests in Simulator (SDK 3.0.7). Is this a known issue? I've tried a couple of ways, here.

module Tests {
class SimpleTest {
function add(a, b) {
return a + b;
}
(:test)
function test(logger) {
logger.debug("Createing callback...");
var m = method(:add);
logger.debug("Created callback.");

logger.debug("Calling callback...");
var res = m.invoke(1, 2);
logger.debug("Callback result: " + res);

return true;
}
}
}


The output for this test is:
Executing test Tests.SimpleTest.test...
DEBUG (14:47): Createing callback...
Failed invoking <symbol>
Invalid Value
ERROR


I've tried the following code as well (replaced "method()" call with "new Method()"):
module Tests {
class SimpleTest {
function add(a, b) {
return a + b;
}
(:test)
function test(logger) {
logger.debug("Createing callback...");
var m = new Toybox.Lang.Method(self, :add);
logger.debug("Created callback.");

logger.debug("Calling callback...");
var res = m.invoke(1, 2);
logger.debug("Callback result: " + res);

return true;
}
}
}


This produces a slightly different output:
Executing test Tests.SimpleTest.test...
DEBUG (14:54): Createing callback...
DEBUG (14:54): Created callback.
DEBUG (14:54): Calling callback...
Failed invoking <symbol>
Symbol Not Found Error
ERROR


However, extracting the "add()" into a separate module works:
module Ops {
function add(a, b) {
return a + b;
}
}

module Tests {
class SimpleTest {
(:test)
function test(logger) {
logger.debug("Createing callback...");
var m = new Toybox.Lang.Method(Ops, :add);
logger.debug("Created callback.");

logger.debug("Calling callback...");
var res = m.invoke(1, 2);
logger.debug("Callback result: " + res);

return true;
}
}
}


It produces the following output:
Executing test Tests.SimpleTest.test...
DEBUG (15:05): Createing callback...
DEBUG (15:05): Created callback.
DEBUG (15:05): Calling callback...
DEBUG (15:05): Callback result: 3
PASS


A couple of notes:
  • I didn't try callbacks on real devices.
  • I did try this code only in unit tests.
  • I would not like to remove this logic from unit tests, because I'm covering some utility functions, which I need to get tested.
  • Methods that are not global and have the (:test) annotation are supposed to be static. This is mentioned in the Programmer's Guide..

    https://developer.garmin.com/connect...test#unittests


    Unit tests are written mostly like any other class, module, or function in Monkey C, but have the following requirements:
    • Tests methods must be marked with the :test annotation
    • Test methods must take a Logger object
    • Tests methods that are not global (part of a test class or custom test module) must be static methods


    Most of the time test code does not try to access members or methods of the containing class or module directly, so this requirement doesn't matter. But since you're trying to reference self (implicitly via method(:add) and explicitly via self.method(:add)), it becomes a problem.

    If you make the test function static, and you create an object instance to test, it seems to work just fine.

    module Tests {
    class SimpleTest {
    function add(a, b) {
    return a + b;
    }
    (:test) static function test(logger) {

    var obj = new SimpleTest();

    logger.debug("Createing callback...");
    var m = obj.method(:add);
    logger.debug("Created callback.");

    logger.debug("Calling callback...");
    var res = m.invoke(1, 2);
    logger.debug("Callback result: " + res);

    return true;
    }
    }
    }


    I think we could do better here by reporting an error if a class or module function is found to have a test annotation and is not explicitly declared static. We could also go one step further and just tell the compiler that any function with a test annotation is static.

    Travis
  • Former Member
    Former Member
    Travis.ConnectIQ thanks! That hint about static test methods solved another problem as well - the "instanceof" is not working without it, claiming it cannot resolve class name (cannot find symbol). Weird error message - I would have never figured it out myself.