Frage

Ich bin ein Anfänger Lua. Ich bin Unit-Tests Lua 5.1 Code LUNITY und LeMock .

Meine Klasse ist Storagemanager. Ich bin Einheit ihre Last () Methode zu testen, welche Dateien von der Festplatte geladen wird. Ich will nicht meine Einheit auf tatsächliche Dateien auf dem tatsächlichen Disk abhängig prüft, ob zu testen.

Also, ich versuche, die I / O-Abhängigkeit mit einem Mock-Objekt zu injizieren und dieses Objekts Verhalten während meines Tests zu überprüfen. Ich kann nicht herausfinden, wie die I / O-Objekt mit einer Syntax zu verwenden, die, wenn sie durch meine beiden Mock-basierten Gerät zu testen und den „echten Code“.

genannt funktioniert

Wie kann ich den Code (die Last () -Methode, vorzugsweise) ändern, so dass sie ihre Arbeit tun, wenn entweder von Unit-Test (das eine ohne das Mock genannt ist vorübergehend, bis ich das herausgefunden bekommen - es ist der ähnelt Code, der später tatsächlich die Methode im Test)?

rufen

Hinweis 1:. Wenn Sie diese Tests durchführen, denken Sie daran, dass die „ohne Mock“ Test eine Datei auf der Festplatte, deren Dateinamen erwartet einstimmt VALID_FILENAME

Hinweis 2: Ich dachte über pcall der try / catch-ähnliches Verhalten mit einer Leitung oder die andere (siehe storageManager.lua Linien 11 und 12) auszuführen. Unter der Annahme, dass es sogar möglich ist, fühlt es sich wie ein Hack, und es fängt Fehler könnte ich später geworfen werden soll (außer Last ()). Bitte erläutern Sie diese Option, wenn Sie keine andere Möglichkeit sehen.

test_storageManager.lua:

 1 require "StorageManager"
 2 require "lunity"
 3 require "lemock"
 4 module("storageManager", package.seeall, lunity)
 5 
 6 VALID_FILENAME = "storageManagerTest.dat"
 7 
 8 function setup()
 9     mc = lemock.controller()
10 end
11 
12 function test_load_reads_file_properly()
13     io_mock = mc:mock()
14     file_handle_mock = mc:mock()
15     io_mock:open(VALID_FILENAME, "r");mc:returns(file_handle_mock)
16     file_handle_mock:read("*all")
17     file_handle_mock:close()
18     mc:replay()
19     storageManager = StorageManager:new{ io = io_mock }
20     storageManager:load(VALID_FILENAME)
21     mc:verify()
22 end
23 
24 function test_load_reads_file_properly_without_mock()
25     storageManager = StorageManager:new()
26     storageManager:load(VALID_FILENAME)
27 end
28 
29 runTests{useANSI = false}

storageManager.lua:

 1 StorageManager = {}
 2 
 3 function StorageManager.new (self,init)
 4     init = init or { io=io } -- I/O dependency injection attempt
 5     setmetatable(init,self)
 6     self.__index = self
 7     return init
 8 end
 9 
10 function StorageManager:load(filename)
11     file_handle = self['io'].open(self['io'], filename, "r") -- works w/ mock
12     -- file_handle = io.open(filename, "r") -- works w/o mock
13     result = file_handle:read("*all")
14     file_handle:close()
15     return result
16 end

Edit:

passieren Diese Klassen beiden Tests. Vielen Dank an die RBerteig.

test_storageManager.lua

 1 require "admin.StorageManager"
 2 require "tests.lunity"
 3 require "lib.lemock"
 4 module("storageManager", package.seeall, lunity)
 5 
 6 VALID_FILENAME = "storageManagerTest.dat"
 7 
 8 function setup()
 9     mc = lemock.controller()
10 end
11
12 function test_load_reads_file_properly()
13     io_mock = mc:mock()
14     file_handle_mock = mc:mock()
15     io_mock.open(VALID_FILENAME, "r");mc:returns(file_handle_mock)
16     file_handle_mock:read("*all")
17     file_handle_mock:close()
18     mc:replay()
19     local saved_io = _G.io
20     _G.io = io_mock
21     package.loaded.io = io_mock
22     storageManager = StorageManager:new()
23     storageManager:load(VALID_FILENAME)
24     _G.io = saved_io
25     package.loaded.io = saved_io
26     mc:verify()
27 end
28
29 function test_load_reads_file_properly_without_mock()
30     storageManager = StorageManager:new()
31     storageManager:load(VALID_FILENAME)
32 end
33
34 runTests{useANSI = false}

storageManager.lua

 1 StorageManager = {}
 2 
 3 function StorageManager.new (self,init)
 4     init = init or {}
 5     setmetatable(init,self)
 6     self.__index = self
 7     return init
 8 end
 9 
10 function StorageManager:load(filename)
11     file_handle = io.open(filename, "r")
12     result = file_handle:read("*all")
13     file_handle:close()
14     return result
15 end
War es hilfreich?

Lösung

Ich denke, dass Sie das Problem machen schwieriger, als es sein muss.

Unter der Annahme, dass das Modul storageManager.lua nicht selbst io Modul lokalisierende, dann alles, was Sie tun müssen, ist die globale io mit Ihrem Mock-Objekt zu ersetzen, während der Test läuft.

Wenn das Modul das io Objekt für die Leistung tut lokalisieren, dann müßten Sie den neuen Wert von io injizieren, bevor das Modul geladen werden. Dies könnte bedeuten, dass Sie den Anruf tätigen müssen Teil des Testfall-Setup require (und eine passende Bereinigung, die alle Spuren des Moduls von package.loaded und _G entfernt), so dass es unterschiedlich in verschiedenen Testfällen verspottet werden kann. WinImage

Edit:

Durch ein Modul für Performance lokalisierende meine ich das Lua Idiom des Kopierens der Methoden des Moduls in lokale Variablen im Namensraum des Moduls. Zum Beispiel:

-- somemodule.lua
require "io"
require "math"

-- copy io and math to local variables
local io,math=io,math

-- begin the module itself, note that package.seeall is not used so globals are
-- not visible after this point
module(...)

function doMathAndIo()
    -- does something interesting here
end

Wenn Sie dies tun, werden die Verweise auf die Lager Module io und math sind zur Zeit gemacht, dass require "somemodule" ausgeführt wird. Ersetzen eine dieser beiden Module nach dem Aufruf mit einer verspottet Version require() wird nicht wirksam sein.

effektiv Um ein Modul zu verspotten, die mit diesem Idiom verwendet wird, würden Sie das Mock-Objekt an der richtigen Stelle müssen vor der Aufruf von require().

Hier ist eine, wie ich gehen würde, das io-Objekt für die Dauer des Anrufs in einem Testfall zu ersetzen:

function test_load_reads_file_properly()
    io_mock = mc:mock()
    file_handle_mock = mc:mock()
    io_mock:open(VALID_FILENAME, "r");mc:returns(file_handle_mock)
    file_handle_mock:read("*all")
    file_handle_mock:close()
    mc:replay()

    local saved_io = _G.io
    _G.io = io_mock
    package.loaded.io = io_mock
    storageManager = StorageManager:new{ }
    storageManager:load(VALID_FILENAME)
    _G.io = saved_io
    package.loaded.io = saved_io
    mc:verify()
end

Ich kann nicht das reale Objekt werden die Wiederherstellung genau im richtigen Moment, und das ist nicht getestet, aber es sollte Sie in die richtige Richtung zeigen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top