Mocha deve ser usado em testes de unidade para os tipos Mock Object ou Test Stub de Test Double, não para os tipos Fake Object ou Test Spy. Embora fosse possível estender o Mocha para permitir a implementação de fakes e espiões, optamos por mantê-lo focado em mocks e stubs.
Instale a versão mais recente da gem com o seguinte comando…
$ gem install mocha
Nota: Se você pretende usar o Mocha com Test::Unit ou Minitest, você só deve configurar o Mocha após carregar a biblioteca de testes relevante...
require 'rubygems'
gem 'mocha'
require 'test/unit'
require 'mocha/test_unit'
require 'rubygems'
gem 'mocha'
require 'minitest/autorun'
require 'mocha/minitest'
Se você estiver usando o Bundler, inclua o Mocha no Gemfile
e configure o Mocha mais tarde, quando souber que a biblioteca de teste foi carregada...
# Gemfile
gem 'mocha'
# Elsewhere after Bundler has loaded gems e.g. after `require 'bundler/setup'`
require 'test/unit'
require 'mocha/test_unit'
# Gemfile
gem 'mocha'
# Elsewhere after Bundler has loaded gems e.g. after `require 'bundler/setup'`
require 'minitest/autorun'
require 'mocha/minitest'
RSpec inclui um adaptador mocha. Basta dizer ao RSpec que você deseja zombar com :mocha
:
# Gemfile in Rails app
gem 'mocha'
# Within `spec/spec_helper.rb`
RSpec . configure do | config |
config . mock_with :mocha
end
Nota: Não há necessidade de usar uma instrução require para configurar o Mocha; O RSpec faz isso sozinho.
# In e.g. features/support/mocha.rb
require 'mocha/api'
World ( Mocha :: API )
Around do | scenario , block |
begin
mocha_setup
block . call
mocha_verify
ensure
mocha_teardown
end
end
Se você estiver carregando o Mocha usando o Bundler em um aplicativo Rails, você deve configurar o Mocha manualmente, por exemplo, na parte inferior do seu test_helper.rb
.
Observe que desde Rails v4 (pelo menos), ActiveSupport::TestCase
herdou de Minitest::Test
ou de seus equivalentes anteriores. Portanto, a menos que você esteja usando explicitamente Test::Unit, provavelmente estará usando o Minitest.
# Gemfile in Rails app
gem 'mocha'
# At bottom of test_helper.rb (or at least after `require 'rails/test_help'`)
require 'mocha/minitest'
Siga as instruções para a estrutura de teste relevante na seção Bundler, mas certifique-se de que o arquivo Mocha relevante ( mocha/minitest
, mocha/test_unit
ou mocha/api
) seja necessário após o carregamento da estrutura de teste, por exemplo, na parte inferior de test_helper.rb
ou spec_helper.rb
, ou pelo menos depois que rails/test_help
for necessário.
extend
a classe não funcionava no Ruby v1.8. Consulte test/acceptance/stub_method_defined_on_module_and_aliased_test.rb
para obter um exemplo desse comportamento. require 'test/unit'
require 'mocha/test_unit'
class MiscExampleTest < Test :: Unit :: TestCase
def test_mocking_a_class_method
product = Product . new
Product . expects ( :find ) . with ( 1 ) . returns ( product )
assert_equal product , Product . find ( 1 )
end
def test_mocking_an_instance_method_on_a_real_object
product = Product . new
product . expects ( :save ) . returns ( true )
assert product . save
end
def test_stubbing_instance_methods_on_real_objects
prices = [ stub ( pence : 1000 ) , stub ( pence : 2000 ) ]
product = Product . new
product . stubs ( :prices ) . returns ( prices )
assert_equal [ 1000 , 2000 ] , product . prices . collect { | p | p . pence }
end
def test_stubbing_an_instance_method_on_all_instances_of_a_class
Product . any_instance . stubs ( :name ) . returns ( 'stubbed_name' )
product = Product . new
assert_equal 'stubbed_name' , product . name
end
def test_traditional_mocking
object = mock ( 'object' )
object . expects ( :expected_method ) . with ( :p1 , :p2 ) . returns ( :result )
assert_equal :result , object . expected_method ( :p1 , :p2 )
end
def test_shortcuts
object = stub ( method1 : :result1 , method2 : :result2 )
assert_equal :result1 , object . method1
assert_equal :result2 , object . method2
end
end
class Enterprise
def initialize ( dilithium )
@dilithium = dilithium
end
def go ( warp_factor )
warp_factor . times { @dilithium . nuke ( :anti_matter ) }
end
end
require 'test/unit'
require 'mocha/test_unit'
class EnterpriseTest < Test :: Unit :: TestCase
def test_should_boldly_go
dilithium = mock ( )
dilithium . expects ( :nuke ) . with ( :anti_matter ) . at_least_once # auto-verified at end of test
enterprise = Enterprise . new ( dilithium )
enterprise . go ( 2 )
end
end
class Order
attr_accessor :shipped_on
def total_cost
line_items . inject ( 0 ) { | total , line_item | total + line_item . price } + shipping_cost
end
def total_weight
line_items . inject ( 0 ) { | total , line_item | total + line_item . weight }
end
def shipping_cost
total_weight * 5 + 10
end
class << self
def find_all
# Database.connection.execute('select * from orders...
end
def number_shipped_since ( date )
find_all . select { | order | order . shipped_on > date } . length
end
def unshipped_value
find_all . inject ( 0 ) { | total , order | order . shipped_on ? total : total + order . total_cost }
end
end
end
require 'test/unit'
require 'mocha/test_unit'
class OrderTest < Test :: Unit :: TestCase
# illustrates stubbing instance method
def test_should_calculate_shipping_cost_based_on_total_weight
order = Order . new
order . stubs ( :total_weight ) . returns ( 10 )
assert_equal 60 , order . shipping_cost
end
# illustrates stubbing class method
def test_should_count_number_of_orders_shipped_after_specified_date
now = Time . now ; week_in_secs = 7 * 24 * 60 * 60
order_1 = Order . new ; order_1 . shipped_on = now - 1 * week_in_secs
order_2 = Order . new ; order_2 . shipped_on = now - 3 * week_in_secs
Order . stubs ( :find_all ) . returns ( [ order_1 , order_2 ] )
assert_equal 1 , Order . number_shipped_since ( now - 2 * week_in_secs )
end
# illustrates stubbing instance method for all instances of a class
def test_should_calculate_value_of_unshipped_orders
Order . stubs ( :find_all ) . returns ( [ Order . new , Order . new , Order . new ] )
Order . any_instance . stubs ( :shipped_on ) . returns ( nil )
Order . any_instance . stubs ( :total_cost ) . returns ( 10 )
assert_equal 30 , Order . unshipped_value
end
end
Mocha atualmente não tenta ser thread-safe.
A resposta curta é não. No código multithread, as exceções Mocha podem ser geradas em um thread diferente daquele que está executando o teste e, portanto, uma exceção Mocha pode não ser interceptada corretamente pelo código de tratamento de exceções Mocha.
Talvez, mas provavelmente não. A simulação parcial altera o estado dos objetos no ObjectSpace
que é compartilhado por todos os threads no processo Ruby e esse acesso ao que é efetivamente um estado global não é sincronizado. Assim, por exemplo, se dois testes estiverem sendo executados simultaneamente e um usar #any_instance
para modificar uma classe, ambos os testes verão essas alterações imediatamente.
Stubs e expectativas são basicamente a mesma coisa. Um stub é apenas uma expectativa de zero ou mais invocações. O método Expectation#stubs
é um açúcar sintático para tornar a intenção do teste mais explícita.
Quando um método é invocado em um objeto simulado, o objeto simulado pesquisa suas expectativas, do mais novo ao mais antigo, para encontrar um que corresponda à invocação. Após a invocação, a expectativa de correspondência poderá parar de corresponder a outras invocações.
Veja a documentação do Mocha::Mock
para mais detalhes.
Se desejar, o Mocha pode gerar um aviso ou gerar uma exceção quando:
Veja a documentação do Mocha::Configuration
para mais detalhes.
MOCHA_OPTIONS
é uma variável de ambiente cujo valor pode ser definido como uma lista separada por vírgulas, para que possamos especificar múltiplas opções, por exemplo, MOCHA_OPTIONS=debug,use_test_unit_gem
. Apenas os seguintes valores são atualmente reconhecidos e têm efeito:
debug
: ativa um modo de depuração que gerará backtraces para cada aviso de descontinuação. Isso é útil para descobrir onde estão as chamadas obsoletas no conjunto de testes.Veja esta lista de contribuidores.
Atualize o arquivo RELEASE.md com um resumo das alterações
Coloque a versão em lib/mocha/version.rb
Confirmar e enviar para GitHub
Verifique se a compilação do CircleCI está sendo aprovada - https://app.circleci.com/pipelines/github/freerange/mocha
Gerar documentação:
$ MOCHA_GENERATE_DOCS=true bundle install
$ MOCHA_GENERATE_DOCS=true rake generate_docs
$ curl -u < email-address > -H ' OTP: ' https://rubygems.org/api/v1/api_key.yaml > ~ /.gem/credentials ; chmod 0600 ~ /.gem/credentials
$ rake release
[runs tests]
mocha 1.2.0 built to pkg/mocha-1.2.0.gem.
Tagged v1.2.0.
Pushed git commits and tags.
Pushed mocha 1.2.0 to rubygems.org.
Mocha foi inicialmente colhido em projetos da Reevoo. Sua sintaxe é fortemente baseada na do jMock.
© Direitos Autorais James Mead 2006
Você pode usar, copiar e redistribuir esta biblioteca sob os mesmos termos do próprio Ruby ou sob a licença do MIT.