ist es zwei Lösungen: Umleitung wo puts
zu (das schreibt Lösung, die von @cldwalker oben angegeben wurde) oder die puts
-Methode selbst als No-Op zu überschreiben. (Die Implementierung sollte offensichtlich sein: module Kernel; def puts(*args) end end
).
In diesem Fall, was wirklich wäre die beste Lösung ist "hören auf Ihre Tests". Denn oft, wenn etwas schwierig zu testen ist, versuchen Ihre Tests, Ihnen zu sagen, dass etwas mit Ihrem Design nicht stimmt. In diesem Fall rieche ich eine Verletzung des Prinzips der einfachen Verantwortung: Warum muss ein Model-Objekt wissen, wie man in die Konsole schreibt? Seine Verantwortung ist ein Domain-Konzept, nicht protokollieren! Dafür sind Logger-Objekte da! Eine alternative Lösung wäre also, dass das Model-Objekt die Verantwortung für die Protokollierung an ein Logger-Objekt delegiert und die Abhängigkeitsinjektion verwendet, um das Model-Objekt mit einem geeigneten Logger-Objekt zu injizieren. Auf diese Weise können Sie einfach einen gefälschten Logger für den Test injizieren.Hier ein Beispiel:
#!/usr/bin/env ruby
class SomeModel
def initialize(logger=Kernel) @logger = logger end
def some_method_that_logs; @logger.puts 'bla' end
end
require 'test/unit'
require 'stringio'
class TestQuietLogging < Test::Unit::TestCase
def setup; @old_stdout, $> = $>, (@fake_logdest = StringIO.new) end
def teardown; $> = @old_stdout end
def test_that_default_logging_is_still_noisy
SomeModel.new.some_method_that_logs
assert_equal "bla\n", @fake_logdest.string
end
def test_that_logging_can_be_made_quiet
fake_logger = Object.new
def fake_logger.puts *args; end
SomeModel.new(fake_logger).some_method_that_logs
assert_equal '', @fake_logdest.string
end
end
Zumindest sollte das Model-Objekt nehmen Sie das IO
Objekt, dass es - als Argument protokolliert, so dass Sie einfach StringIO.new
in sie für den Test injizieren:
#!/usr/bin/env ruby
class SomeModel
def initialize(logdest=$>) @logdest = logdest end
def some_method_that_logs; @logdest.puts 'bla' end
end
require 'test/unit'
require 'stringio'
class TestQuietLogging < Test::Unit::TestCase
def setup; @old_stdout, $> = $>, (@fake_logdest = StringIO.new) end
def teardown; $> = @old_stdout end
def test_that_default_logging_is_still_noisy
SomeModel.new.some_method_that_logs
assert_equal "bla\n", @fake_logdest.string
end
def test_that_logging_can_be_made_quiet
fake_logdest = (@fake_logdest = StringIO.new)
SomeModel.new(fake_logdest).some_method_that_logs
assert_equal '', @fake_logdest.string
assert_equal "bla\n", fake_logdest.string
end
end
Wenn Sie noch in der Lage sein wollen, nur puts whatever
in Ihrem Modell zu sagen, oder Sie haben Angst, dass jemand vergessen puts
auf dem Logger-Objekt aufrufen, können Sie Ihre eigenen bereitstellen (privat) legt Methode:
class SomeModel
def initialize(logdest=$>) @logdest = logdest end
def some_method_that_logs; puts 'bla' end
private
def puts(*args) @logdest.puts *args end
end
Danke, das bedeutet wahrscheinlich, dass es keinen Standard-eingebauten Weg gibt? – denchr
Das funktioniert übrigens sehr schön – denchr
Ziemlich ordentliche Lösung, bravo! – khelll