diff --git a/dist/luarocks/.version b/dist/luarocks/.version index c088e13..fb76855 100644 --- a/dist/luarocks/.version +++ b/dist/luarocks/.version @@ -1 +1 @@ -1.0.0-1 \ No newline at end of file +1.0.1-1 \ No newline at end of file diff --git a/dist/luarocks/mocka-1.0.1-1.rockspec b/dist/luarocks/mocka-1.0.1-1.rockspec new file mode 100644 index 0000000..ce8fbbd --- /dev/null +++ b/dist/luarocks/mocka-1.0.1-1.rockspec @@ -0,0 +1,88 @@ +package = "mocka" +version = "1.0.1-1" +source = { + url = "git+https://github.com/adobe/mocka.git", + tag = "v1.0.1" +} +description = { + summary = "The one lua testing framework that mocks classes, runs with real classes from your project, has nginx embeded methods for openresty individual testing. Has a suite of libraries preinstalled and you can specify libraries to install.", + license = "Apache2" +} +dependencies = { + "luafilesystem", "lua-websockets", "lua-cjson = 2.1.0", "lua-ev", "luabitop", "lua-resty-iputils", "penlight", "ldoc", "luacov", "luacov-coveralls", "luacov-cobertura", "luacheck" +} +build = { + type = "builtin", + platforms = { + haiku = { + modules = { + ["luacov.cobertura.luatoxml"] = "luacov-cobertura/luacov/cobertura/luatoxml.lua", + ["luacov.reporter.cobertura"] = "luacov-cobertura/luacov/reporter/cobertura.lua", + mocka = "src/main/lua/com/adobe/test/framework/Mocka.lua", + ["mocka.debugger"] = "src/main/lua/com/adobe/test/framework/debugger.lua", + ["mocka.default_mocks"] = "src/main/lua/com/adobe/test/framework/default_mocks.lua", + ["mocka.http_util"] = "src/main/lua/com/adobe/test/framework/http_util.lua", + ["mocka.messaging_queue"] = "src/main/lua/com/adobe/test/framework/messaging_queue.lua", + ["mocka.ngx_suite"] = "src/main/lua/com/adobe/test/suites/run_ngx_tests.lua", + ["mocka.suite"] = "src/main/lua/com/adobe/test/suites/run_tests.lua", + ["mocka.ws_server"] = "src/main/lua/com/adobe/test/framework/ws_server.lua" + } + }, + macosx = { + modules = { + ["luacov.cobertura.luatoxml"] = "luacov-cobertura/luacov/cobertura/luatoxml.lua", + ["luacov.reporter.cobertura"] = "luacov-cobertura/luacov/reporter/cobertura.lua", + mocka = "src/main/lua/com/adobe/test/framework/Mocka.lua", + ["mocka.debugger"] = "src/main/lua/com/adobe/test/framework/debugger.lua", + ["mocka.default_mocks"] = "src/main/lua/com/adobe/test/framework/default_mocks.lua", + ["mocka.http_util"] = "src/main/lua/com/adobe/test/framework/http_util.lua", + ["mocka.messaging_queue"] = "src/main/lua/com/adobe/test/framework/messaging_queue.lua", + ["mocka.ngx_suite"] = "src/main/lua/com/adobe/test/suites/run_ngx_tests.lua", + ["mocka.suite"] = "src/main/lua/com/adobe/test/suites/run_tests.lua", + ["mocka.ws_server"] = "src/main/lua/com/adobe/test/framework/ws_server.lua" + } + }, + mingw32 = { + modules = { + ["luacov.cobertura.luatoxml"] = "luacov-cobertura/luacov/cobertura/luatoxml.lua", + ["luacov.reporter.cobertura"] = "luacov-cobertura/luacov/reporter/cobertura.lua", + mocka = "src/main/lua/com/adobe/test/framework/Mocka.lua", + ["mocka.debugger"] = "src/main/lua/com/adobe/test/framework/debugger.lua", + ["mocka.default_mocks"] = "src/main/lua/com/adobe/test/framework/default_mocks.lua", + ["mocka.http_util"] = "src/main/lua/com/adobe/test/framework/http_util.lua", + ["mocka.messaging_queue"] = "src/main/lua/com/adobe/test/framework/messaging_queue.lua", + ["mocka.ngx_suite"] = "src/main/lua/com/adobe/test/suites/run_ngx_tests.lua", + ["mocka.suite"] = "src/main/lua/com/adobe/test/suites/run_tests.lua", + ["mocka.ws_server"] = "src/main/lua/com/adobe/test/framework/ws_server.lua" + } + }, + unix = { + modules = { + ["luacov.cobertura.luatoxml"] = "luacov-cobertura/luacov/cobertura/luatoxml.lua", + ["luacov.reporter.cobertura"] = "luacov-cobertura/luacov/reporter/cobertura.lua", + mocka = "src/main/lua/com/adobe/test/framework/Mocka.lua", + ["mocka.debugger"] = "src/main/lua/com/adobe/test/framework/debugger.lua", + ["mocka.default_mocks"] = "src/main/lua/com/adobe/test/framework/default_mocks.lua", + ["mocka.http_util"] = "src/main/lua/com/adobe/test/framework/http_util.lua", + ["mocka.messaging_queue"] = "src/main/lua/com/adobe/test/framework/messaging_queue.lua", + ["mocka.ngx_suite"] = "src/main/lua/com/adobe/test/suites/run_ngx_tests.lua", + ["mocka.suite"] = "src/main/lua/com/adobe/test/suites/run_tests.lua", + ["mocka.ws_server"] = "src/main/lua/com/adobe/test/framework/ws_server.lua" + } + }, + win32 = { + modules = { + ["luacov.cobertura.luatoxml"] = "luacov-cobertura/luacov/cobertura/luatoxml.lua", + ["luacov.reporter.cobertura"] = "luacov-cobertura/luacov/reporter/cobertura.lua", + mocka = "src/main/lua/com/adobe/test/framework/Mocka.lua", + ["mocka.debugger"] = "src/main/lua/com/adobe/test/framework/debugger.lua", + ["mocka.default_mocks"] = "src/main/lua/com/adobe/test/framework/default_mocks.lua", + ["mocka.http_util"] = "src/main/lua/com/adobe/test/framework/http_util.lua", + ["mocka.messaging_queue"] = "src/main/lua/com/adobe/test/framework/messaging_queue.lua", + ["mocka.ngx_suite"] = "src/main/lua/com/adobe/test/suites/run_ngx_tests.lua", + ["mocka.suite"] = "src/main/lua/com/adobe/test/suites/run_tests.lua", + ["mocka.ws_server"] = "src/main/lua/com/adobe/test/framework/ws_server.lua" + } + } + } +} diff --git a/src/main/lua/com/adobe/test/framework/Mocka.lua b/src/main/lua/com/adobe/test/framework/Mocka.lua index 6fcb662..fe06f5f 100644 --- a/src/main/lua/com/adobe/test/framework/Mocka.lua +++ b/src/main/lua/com/adobe/test/framework/Mocka.lua @@ -111,10 +111,16 @@ end -- @param t object - the object to clone -- local function _clone (t) -- shallow-copy - if type(t) ~= "table" then return t end + if type(t) ~= "table" then + return t + end + local meta = getmetatable(t) local target = {} - for k, v in pairs(t) do target[k] = v end + for k, v in pairs(t) do + target[k] = v + end + setmetatable(target, meta) return target end @@ -129,44 +135,66 @@ local function _makeDoReturnFunction(obj) end end +local function __prepareSpy(path, class) + local success = false + + for method, impl in pairs(class) do + --- put all but not privates line __index + -- TODO: maybe in the future I can index private methods + success = true + if impl ~= nil and type(impl) == 'function' + and not string.find(method, "__") then + spies[path]["__" .. method] = { + calls = 0, + name = path .. "." .. method, + latestCallWith = nil, + doReturn = impl + } + spies[path][method] = _makeFunction(method, spies[path]) + end + end + return success +end + +local function __doSpy(path, class) + local mapObj = {} + local success = false + for method, method_real in pairs(class) do + -- don't index private methods + -- TODO: maybe in the future I can index private methods + success = true + if not string.find(method, "__") and type(method_real) == 'function' then + mapObj[method] = spies[path]["__" .. method] + mapObj[method]["stub"] = _makeDoReturnFunction(spies[path]["__" .. method]) + end + end + + return success, mapObj +end + local function __makeSpy(path) if path and not mirror[path] then return end + if path then - for method, impl in pairs(mirror[path]) do - --- put all but not privates line __index - -- TODO: maybe in the future I can index private methods - if impl ~= nil and type(impl) == 'function' - and not string.find(method, "__") then - spies[path]["__" .. method] = { - calls = 0, - name = path .. "." .. method, - latestCallWith = nil, - doReturn = impl - } - spies[path][method] = _makeFunction(method, spies[path]) - end + local success = __prepareSpy(path, mirror[path]) + + -- maybe class is auto instantiated in require - singleton like + if not success then + __prepareSpy(path, getmetatable(mirror[path])) end end if not path then for k, v in pairs(mirror) do if type(v) == 'table' then - for method, impl in pairs(v) do - --- put all but not privates line __index - -- TODO: maybe in the future I can index private methods - if impl ~= nil and type(impl) == 'function' - and not string.find(method, "__") then - spies[k]["__" .. method] = { - calls = 0, - name = k .. "." .. method, - latestCallWith = nil, - doReturn = impl - } - spies[k][method] = _makeFunction(method, spies[k]) - end + local success = __prepareSpy(k, v) + + -- maybe class is auto instantiated in require - singleton like + if not success then + __prepareSpy(k, getmetatable(v)) end end end @@ -204,15 +232,11 @@ function spy(class, method, fn) end - local mapObj = {} + local success, mapObj = __doSpy(class, mirror[class]) - for method, method_real in pairs(mirror[class]) do - -- don't index private methods - -- TODO: maybe in the future I can index private methods - if not string.find(method, "__") and type(method_real) == 'function' then - mapObj[method] = spies[class]["__" .. method] - mapObj[method]["stub"] = _makeDoReturnFunction(spies[class]["__" .. method]) - end + -- auto generated singleton class + if not success then + success, mapObj = __doSpy(class, getmetatable(mirror[class])) end if method and fn then diff --git a/src/test/adobe/mocka/HealthcheckTest.lua b/src/test/adobe/mocka/HealthcheckTest.lua index 4ce30ca..ac5c70d 100644 --- a/src/test/adobe/mocka/HealthcheckTest.lua +++ b/src/test/adobe/mocka/HealthcheckTest.lua @@ -92,3 +92,27 @@ test('properties passed to mock constructor should be there', function() local mockedConstructor = require("test.constructor"):new({ foo = "bar"}) assertEquals(mockedConstructor.foo, "bar") end) + +test('ability to lazy mock auto generating classes singleton pattern', function() + spy("src.test.adobe.mocka.auto_running_class", "doSomething", function() + return false + end) + + local original = oldRequire "src.test.adobe.mocka.auto_running_class" + local autoRunning = require "src.test.adobe.mocka.auto_running_class" + + assertEquals(autoRunning:doSomething(), false) + assertEquals(original:doSomething(), true) + +end) + +test('ability to mock auto generating classes singleton pattern post require', function() + local autoRunning = require "src.test.adobe.mocka.auto_running_class" + assertEquals(autoRunning:doSomething(), true) + + spy("src.test.adobe.mocka.auto_running_class", "doSomething", function() + return false + end) + + assertEquals(autoRunning:doSomething(), false) +end) diff --git a/src/test/adobe/mocka/auto_running_class.lua b/src/test/adobe/mocka/auto_running_class.lua new file mode 100644 index 0000000..84ae7ba --- /dev/null +++ b/src/test/adobe/mocka/auto_running_class.lua @@ -0,0 +1,21 @@ +-- +-- Created by IntelliJ IDEA. +-- User: trifan +-- Date: 7/16/18 +-- Time: 19:37 +-- To change this template use File | Settings | File Templates. +-- +local M = {} + +function M:new(o) + local o = o or {} + setmetatable(o, self) + self.__index = self + return o +end + +function M:doSomething() + return true +end + +return M:new()