rspec으로 어떻게 테스트할까요?rspec을 사용하여 다른 클래스의 초기화에 위임하는 메소드를 테스트하는 방법은 무엇입니까?
class SomeClass
def map_url(size)
GoogleMap.new(point: model.location.point, size: size).map_url
end
end
rspec으로 어떻게 테스트할까요?rspec을 사용하여 다른 클래스의 초기화에 위임하는 메소드를 테스트하는 방법은 무엇입니까?
class SomeClass
def map_url(size)
GoogleMap.new(point: model.location.point, size: size).map_url
end
end
테스트가 "매우 결합 조롱하는 취성"보인다는 사실은 코드 자체가 한 번에 너무 많은 일을하고 있다는 신호이다.
은 (어떤 크기의 입력에 대해 "foo는"반환) 의미가map_url
의 구현,보고, 문제를 강조하고 아직 테스트를 통과하려면
class SomeClass
def map_url(size)
GoogleMap.new.map_url
GoogleMap.new(point: model.location.point, size: size)
return "foo"
end
end
주의한다 :
map_url
이 새로 시작된지도에서는 호출되지만 올바른 인수로 시작된지도에서는 호출되지 않습니다.map_url
의 결과가 반환되지 않습니다.나는 당신이 코드를 구조화하는 방식이 실제보다 더 단순하게 보이게한다는 것이 문제라고 주장한다. 결과적으로 테스트가 너무 간단하여 메서드의 동작을 완전히 다루지 못합니다.
이 comment from David Chelimsky
관련 여기 보인다 이그들이 상처를 때 일반적으로 설계 문제가 있기 때문에 당신이 에 테스트를 들어야 제안 TDD에있는 오래 된 가이드 라인이있다. 테스트는 테스트중인 코드의 클라이언트이며, 테스트가 아파하면 코드베이스의 다른 클라이언트를 모두 수행합니다. 이 바로 가기 바로 가기 은 가난한 디자인에 대한 변명 거리가됩니다. 나는 그것을 괴롭히기를 원한다. 은을 해치려해야한다. 그럼 당신은 개별적으로 테스트 할 수 있습니다
class SomeClass def new_map(size) GoogleMap.new(point: model.location.point, size: size) end def map_url(size) new_map(size).map_url end end
:
describe SomeClass do let(:some_class) { SomeClass.new } let(:mock_map) { double('map') } describe "#new_map" do it "returns a GoogleMap with the correct point and size" do map = some_class.new_map('300x600') map.point.should == [1,2] map.size.should == '300x600' end end describe "#map_url" do before do some_class.should_receive(:new_map).with('300x600').and_return(mock_map) end it "initiates a new map of the right size and call map_url on it" do mock_map.should_receive(:map_url) some_class.map_url('300x600') end it "returns the url" do mock_map.stub(map_url: "http://www.example.com") some_class.map_url('300x600').should == "http://www.example.com" end end end
결과를이 충고에 따라
는
, 내가 문제를 분리, 별도의 두 가지 방법으로 첫 번째 분할에게 코드를 건의 할 것 테스트 코드가 길어서 2 개가 아닌 3 개 스펙이 있지만 코드에 포함 된 단계를보다 명확하고 깔끔하게 구분하고 메서드 동작을 완전히 다룰 수 있다고 생각합니다. 이 말이 맞는다면 알려주십시오.
이것이 내가 한 방법입니다. 이처럼 그것을 조롱하는 것은 매우 결합되고 부서지기 쉬운 느낌입니다. 제안?
describe SomeClass do
let(:some_class) { SomeClass.new }
describe "#map_url" do
it "should instantiate a GoogleMap with the correct args" do
GoogleMap.should_receive(:new).with(point: [1,2], size: '300x600') { stub(map_url: nil) }
some_class.map_url('300x600')
end
it "should call map_url on GoogleMap instance" do
GoogleMap.any_instance.should_receive(:map_url)
some_class.map_url('300x600')
end
end
end
거기에 'some_class = SomeClass.new'가 필요하지 않습니까 (예 :'before' 블록)? –
예, 전체 예제로 업데이트되었지만 (예 : – Yeggeps
) 'mock_map'에 인스턴스 변수 대신'let'을 사용합니다. "should"를 사용하지 않도록 예제 이름을 다시 써주십시오. "무언가를한다"대 "뭔가해야한다").:) – doesterr
아마도 주목할만한 것입니다 : 사양은 별도로 테스트 한'GoogleMap'에 의존합니다. 그래서 당신이 그렇게하는지 확인하십시오. 'map_url'의 이름이'mapurl'으로 바뀐'GoogleMap'의 새로운 버전을 상상해보십시오. 위의 사양은 여전히 지나치지 만 다른 곳에서는 오류가 발생합니다. – doesterr
"let"과 "should"의 사용에 관해서는, 두 가지 모두에 동의하고, 그러한 변경을 할 것입니다. –