How to init a Kong cache in tests?

Hi,

The first question: How is the kong cache initialized? I’m asking, because I’ve just written unit tests that touch code where the cache is used, but I received a following error:

attempt to index field 'cache' (a nil value)

caused by calling a function singletons.cache:get(...) in the following code:

-- #################
-- kong_cache.lua
-- #################

local singletons = require("kong.singletons")

local function run_cache(key, options, fetch_data_function, ...)
	-- ...
	local cached_value, error = singletons.cache:get(key, kong_cache_options, fetch_data_function, ...)
	-- ...
end

I’m starting a kong instance, using helpers, in busted tests, but it seems the Kong cache is still unavailable. I’ve looked at tests in a Kong’s repo. As I assume, tests init the cache by means of sending a request to somewhere. Could you confirm that?

The second question: Is there any solution to test a module, which uses the Kong cache, directly by means of calling functions of module (without sending a request to some endpoint)? For example, I’d like to test functions of builder.lua without sending a request in busted tests:

-- ##############
-- builder.lua
-- ##############

-- kong_cache is a wrapper on kong.singletons.cache
local kong_cache = require("kong.custom_modules.kong_cache")

function _M:run() 
    -- This statement uses the kong_cache variable.
end

-- other functions

1 Like

I am having this same question in developing a unit test for a plugin that uses the Kong cache. @Robert.pm, were you ever able to figure this out?

Or does anyone have any information on how to access the cache in a unit test of a custom plugin?

Hi @Tim_Kelley

You shouldn’t directly access Kong’s cache in tests unless you are testing the cache system. I suggest you take a look at how this is tested in existing plugins, in the key-auth plugin for instance (spec/03-plugins/09-key-auth/03-invalidations_spec.lua).

Thanks for the reply @vinicius.mignot! I understand what that is doing, though it isn’t quite what I want to accomplish.

Here is my scenario. I have a plugin that is retrieving data from a URL (defined in plugin config). The response data is then cached and used for individual requests.

What I am wanting to do in the unit test is have a way to “mock” or pre-load the cache with data set in the unit test. I have attempted to go the route of mocking my module using the “package.loaded[“module”]” method as well as using the mockers.setup function from the Kong test helpers. Neither of those worked, so I was going down the route of just trying to pre-populate the cache, such that when the code is executed, it will be retrieved without making an HTTP call. I was struggling with that when I came upon this thread.

Another option I have considered is setting up a mock route in my unit test that would be used as the URL defined in the config that would then return mock data to use.

Just to add, I am running my tests using the kong-pongo utility.

If you happen to know what the best option for accomplishing this might be, any help would be appreciated! Thanks!

I usually prefer to emulate the actual behavior when creating tests, that way you know how your code will behave in the wild. So, if you are testing the caching of a request and then using the result of said cache, I would go the way of sending a request that would be cached, do not take into account the result of the first request (maybe just check if it returned 200) and then send the requests that I actually wanted to check the behavior.

There’s a mocked HTTPS server in the fixtures, but if you want to cache response results, that might not be enough. Probably launching a really simple instance of Nginx, returning a known body using content_by_lua_block is what you need.