lunarmodules / busted

Elegant Lua unit testing.
https://lunarmodules.github.io/busted/
MIT License
1.39k stars 184 forks source link

Does busted support the customization function return value in unit test #648

Closed ffbh123456 closed 3 years ago

ffbh123456 commented 3 years ago

I have two functions:

function A(args)
        -- connect database
    return result
end
function B()
       -- do something
       local result = A(args)
       -- do something
end

Function A needs to connect to the database. I don’t want to connect to the database in my unit test, but this function has a return value. The return value is used in function B. I hope that I can get my own customization function result without actually executing function A. Is there any way to return the customization function value?

NickFlexer commented 3 years ago

Hello! Yes, you can override the behavior of your function using stubs.

You want a return value, so you need to use Spies. Here's a simple code example:


-- function you want to test
function B()
    local result = A("my argument")
    return result
end

describe("Some", function ()

    _G.A = function ()
        -- set your result
        return 42
    end

    it("mock", function ()
        spy.on(_G, "A")

        assert.are.equals(B(), 42) -- check function B result
        assert.spy(A).was_called_with("my argument") -- check with what arguments function A was called

        A:revert()
    end)
end)```
ffbh123456 commented 3 years ago

@NickFlexer Hi, Thank you, it works. But I encountered a more complicated situation, please see the picture below, how do I customize the value of result1 and result2 in busted unit test image

NickFlexer commented 3 years ago

if you want a mock package that is called by require you must follow these steps:

  1. describe in a simple table the functions that your code will call and specify the return values ​​for them
  2. mocks the table with spies
  3. specify the resulting table as the result of the package.preload function
  4. call your module under test using require
  5. test it)
  6. remember to revert the stub

example:

describe("Test module", function ()
    it("load module", function ()
        -- 1
        local m = {
            start = function ()
                return 42
            end
        }

        -- 2
        local database = mock(m)

        -- 3
        package.preload["database"] = function ()
            return database
        end

        -- 4
        local test_module = require "test_module"

        -- 5
        assert.are.equals(test_module.B(), 42)
        assert.stub(database.start).was.called_with("my argument")

        -- 6
        mock.revert(database)
    end)
end)
ffbh123456 commented 3 years ago

@NickFlexer Thank you!!! you are really helpfully and explained in detail