Исключение нулевого указателя генерируется, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:
null
. null
. null
, как если бы это был массив. null
, как если бы это был массив. null
как будто это было значение Throwable. Приложения должны бросать экземпляры этого класса, чтобы указать на другие незаконные использования объекта null
.
Ссылка: http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html
Можно "вновь открыть" класс и предоставить новый метод, который делегирует к частному:
class Foo
private
def bar; puts "Oi! how did you reach me??"; end
end
# and then
class Foo
def ah_hah; bar; end
end
# then
Foo.new.ah_hah
Одним путем я сделал это в прошлом:
class foo
def public_method
private_method
end
private unless 'test' == Rails.env
def private_method
'private'
end
end
Можно обойти инкапсуляцию с отправить методом:
myobject.send(:method_name, args)
Это - 'функция' Ruby. :)
были внутренние дебаты во время разработки Ruby 1.9, которая полагала, что наличие send
относится с уважением к конфиденциальности, и send!
игнорируют его, но в конце ничто не изменилось в Ruby 1.9. Проигнорируйте комментарии ниже обсуждения send!
и повреждение вещей.
Просто вновь откройте класс в своем тестовом файле и переопределите метод или методы как общественность. Вы не должны переопределить кишки самого метода, просто передать символ в эти public
вызов.
, Если Вы исходный класс определяетесь как это:
class MyClass
private
def foo
true
end
end
В Вас тестовый файл, просто сделайте что-то вроде этого:
class MyClass
public :foo
end
можно передать несколько символов public
, если Вы хотите выставить больше закрытых методов.
public :foo, :bar
Я, вероятно, склонился бы к использованию instance_eval (). Прежде чем я знал о instance_eval (), однако, я создам производный класс в своем файле модульного теста. Я затем установил бы закрытый метод (методы) быть общедоступным.
В примере ниже, build_year_range метод закрыт в PublicationSearch:: класс ISIQuery. Получение нового класса просто для тестирования позволяет мне устанавливать метод (методы), чтобы быть общедоступным и, поэтому, непосредственно тестируемым. Аналогично, производный класс выставляет переменную экземпляра, названную 'результатом', который не был ранее выставлен.
# A derived class useful for testing.
class MockISIQuery < PublicationSearch::ISIQuery
attr_accessor :result
public :build_year_range
end
В моем модульном тесте у меня есть тестовый сценарий, который инстанцирует класса MockISIQuery и непосредственно тестирует build_year_range () метод.
instance_eval()
мог бы помочь:
--------------------------------------------------- Object#instance_eval
obj.instance_eval(string [, filename [, lineno]] ) => obj
obj.instance_eval {| | block } => obj
------------------------------------------------------------------------
Evaluates a string containing Ruby source code, or the given
block, within the context of the receiver (obj). In order to set
the context, the variable self is set to obj while the code is
executing, giving the code access to obj's instance variables. In
the version of instance_eval that takes a String, the optional
second and third parameters supply a filename and starting line
number that are used when reporting compilation errors.
class Klass
def initialize
@secret = 99
end
end
k = Klass.new
k.instance_eval { @secret } #=> 99
можно использовать его для закрытых методов доступа и переменных экземпляра непосредственно.
Вы могли также рассмотреть использование send()
, который также предоставит Вам доступ к закрытым и защищенным методам (как предложенный James Baker)
, С другой стороны, Вы могли изменить метакласс своего тестового объекта обнародовать частные / защищенные методы, общедоступные только для того объекта.
test_obj.a_private_method(...) #=> raises NoMethodError
test_obj.a_protected_method(...) #=> raises NoMethodError
class << test_obj
public :a_private_method, :a_protected_method
end
test_obj.a_private_method(...) # executes
test_obj.a_protected_method(...) # executes
other_test_obj = test.obj.class.new
other_test_obj.a_private_method(...) #=> raises NoMethodError
other_test_obj.a_protected_method(...) #=> raises NoMethodError
Это позволит Вам назвать эти методы, не влияя на другие объекты того класса. Вы могли вновь открыть класс в рамках своего тестового каталога и обнародовать их для всех экземпляров в рамках Вашего тестового кода, но это могло бы влиять на Ваш тест открытого интерфейса.
Вот общее дополнение к Классу, который я использую. Это - немного больше ружья, чем только обнародование метода, который Вы тестируете, но в большинстве случаев это не имеет значения, и это намного более читаемо.
class Class
def publicize_methods
saved_private_instance_methods = self.private_instance_methods
self.class_eval { public *saved_private_instance_methods }
begin
yield
ensure
self.class_eval { private *saved_private_instance_methods }
end
end
end
MyClass.publicize_methods do
assert_equal 10, MyClass.new.secret_private_method
end
Используя отправляют к доступу, защищенным/закрытым методам , прерваны 1.9, так не рекомендуемое решение.
Вот один простой способ при использовании RSpec:
before(:each) do
MyClass.send(:public, *MyClass.protected_instance_methods)
end
Я уверен, что кто-нибудь трубит и догматично утверждают, что «вы должны только общедоступные методы модульного тестирования; если это требуется модульное тестирование, это не должно быть защищенный или частный метод ", но я не очень заинтересован в дебатах это.
Вы также можете преобразовать их в новый объект, в котором эти методы являются общедоступными, и делегировать им конфиденциально в исходном классе. Это позволит вам тестировать методы без магических метарубов в ваших спецификациях, сохраняя при этом их конфиденциальность.
У меня есть несколько методов, которые защищенный или частный навсегда и уважительные причины
Каковы эти веские причины? Другие языки ООП могут вообще обойтись без частных методов (на ум приходит smalltalk - где частные методы существуют только как соглашение).
]Вместо метода obj.send можно использовать метод singleton. Это еще 3 строки кода в вашем test class и не требует никаких изменений в реальном коде для тестирования.[
] [def obj.my_private_method_publicly (*args)
my_private_method(*args)
end
]
[]В тестовых случаях при тестировании []my_private_method_publicly[
] всякий раз, когда необходимо тестировать []my_private_method[
].[
][]http://mathandprogramming.blogspot.com/2010/01/ruby-testing-private-methods.html[][
] [][]obj.send[
] для private-методов в 1.9 была заменена на []send![
], но позже []send![
] была снова удалена. Так что []obj.send[
] работает отлично. [
Чтобы исправить верхний ответ выше: в Ruby 1.9.1 это Object # send, который отправляет все сообщения, и Object # public_send, который уважает конфиденциальность.