Created
November 8, 2011 05:04
-
-
Save kurko/1347050 to your computer and use it in GitHub Desktop.
SOLID e BDD
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# No ActiveRecord, Client has_one ClientProfile | |
# | |
# ClientProfile tem um campo chamado Twitter. Como é um varchar | |
# e um usuário pode ter 2 contas no Twitter, salvo os dados no | |
# formato "usuario;usuario2;usuario3" neste campo. O problema abaixo gira em torno | |
# do processamento desta string e como testar isto usando os princípios SOLID que | |
# você abordou na sua palestra na RubyConf. | |
# | |
# O split(";") era feito no model, o qual tirei para fora (classe ClientService abaixo). | |
# O problema é: como vou testar com mock se o argumento injetado precisa ser ActiveRecord? | |
# Afinal, vou fazer um loop por Client.client_profile.twitter.split(";").each { ... } | |
# Questão 1: Vê Client.client_profile.twitter.split() no código? Se Client é enviado | |
# a organize_twitter() como argumento no controller abaixo, como testar com mock? | |
# Pois se usar um mock como argumento, vai quebrar tudo. Me parece que há algo | |
# estranho no design, pois como você disse, "Teste quebradiço = Design ruim"... | |
# Questão 2: Eu testava models com dados vindos do DB. Usando Mock, vou testar | |
# o controller (integração) e os Services, mas e os models? Não testarei mais usando Factory | |
# e afins? Ou seja, a única forma de testar resultado real do comportamento da app será por | |
# testes de controller? (já que os services recebem injeção de mocks apenas) | |
# Questão 3: O método organize_twitter() deveria sair de ClientService e ir para outra classe? | |
# Como você interpreta a responsabilidade dele? | |
# app/controller/clients_controller.rb | |
def show | |
client = ClientService.new(session[:company_id]) | |
@client = client.find(Client, params[:id]) | |
@twitter = client.organize_twitter(@client) | |
end | |
# app/services/clients_service.rb | |
# | |
# Todo este método estava num model. Então tirei ele para fora. | |
class ClientService | |
def initialize(company_id) | |
@company_id = company_id | |
end | |
def find(client_active_record, id) | |
client_active_record.by_company(@company_id).find(id) | |
end | |
# Relacionado à Questão 1: Como testarei este método, se o argumento é um ActiveRecord? | |
# Entraria aqui um Wrapper, que faz esse loop todo e então injeta uma array em | |
# vez de um objeto ActiveRecord? Como usar mocks? | |
def organize_twitter(client) | |
twitter = [] | |
client.client_profile.twitter.to_s.gsub(/\s/, '').split(/[\s|,|;]/).each { |t| | |
twitter << { :role => 'client', :username => t } | |
} | |
# Este loop é porque Client has_many Contacts, os quais também têm Twitter. | |
client.contacts.each { |contact| | |
contact.client_profile.twitter.gsub(/\s/, '').split(/[\s|,|;]/).each { |t| | |
twitter << { :role => 'contact', :username => t } | |
} | |
} | |
end | |
end | |
# Meu teste até agora para isto | |
# spec/services/client_spec.rb | |
require './app/services/client_service' | |
describe ClientService do | |
let(:client) { double("a client") } | |
it "loads" do | |
client.stub_chain(:by_company, :find).and_return true | |
ClientService.new(1).find(client, 1).should be_true | |
end | |
it "loads twitter accounts" do | |
# ...aqui eu to penando... | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment