2011-10-17 6 views
2

메소드가 mock 객체에 의해 리턴 된 다른 여러 컨테이너의 집합 인 콜렉션을 캡슐화하는 컨테이너를 리턴하는지 확인하는 방법에 대해 궁금합니다. 즉, 개별 컨테이너의 모든 요소를 ​​포함합니다. 다른 곳에서 컨테이너의 'works'(add/addAll/etc)를 검사하는 테스트가 있기 때문에 작동하는 것을 알 수 있습니다. 그러나 'createsRoadUsersAccordingToAllAddedCreators'아래의 테스트가 어떻게 진행되는지 잘 모르겠습니다.컬렉션을 캡슐화하는 객체를 조롱하기

나는 추가 된 RoadUserCreator 's에 따라 RoadUserContainer를 반환하는 Create를 호출하는 RoadUserCreationDaemon 클래스를 가지고 있습니다. 단순화 된 버전 :

public class RoadUserCreationDaemon { 

    private SimulationManager simulationManager; 
    private List<RoadUserCreator> roadUserCreators; 

    public RoadUserCreationDaemon(SimulationManager simulationManager) { 
     this.simulationManager = simulationManager; 
     roadUserCreators = new ArrayList<RoadUserCreator>(); 
    } 

    public void addRoadUserCreator(RoadUserCreator roadUserCreator) { 
     roadUserCreators.add(roadUserCreator); 
    } 

    public RoadUserContainer createRoadUsers() { 
     RoadUserContainer roadUsers = new RoadUserContainerImpl(); 
     for (RoadUserCreator creator : roadUserCreators) { 
      roadUsers.addAll(createRoadUsers(creator)); 
     } 
     return roadUsers; 
    } 

    public RoadUserContainer createRoadUsers(
      RoadUserCreator roadUserCreator) { 
     return roadUserCreator.create(); 
    } 
} 

나는 공급 창조자와 RoadUserContainer을 반환 createRoadUsers에 대한 테스트를 (JUnit4/JMock2.5.1) 작성하여 시작했다. 아니에요 ... 댓글이 말한대로

@RunWith(JMock.class) 
public class TestRoadUserCreationDaemon { 
    Mockery context = new JUnit4Mockery();  
    private RoadUserCreationDaemon daemon;  
    private RoadUserCreator roadUserCreator;  
    private SimulationManager simulationManager;   
    private RoadUserContainer createdRoadUsers; 

    @Before 
    public void setUp() { 
     simulationManager = context.mock(SimulationManager.class); 
     daemon = new RoadUserCreationDaemon(simulationManager); 

     roadUserCreator = context.mock(RoadUserCreator.class); 
     createdRoadUsers = context.mock(RoadUserContainer.class); 
    }  

    @Test 
    public void createsRoadUsersAccordingToAllAddedCreators() throws Exception { 
     final RoadUserCreator anotherRoadUserCreator = context.mock(RoadUserCreator.class, "anotherRUC"); 
     final RoadUserContainer moreCreatedRoadUsers = context.mock(RoadUserContainer.class, "moreCRU"); 
     context.checking(new Expectations() {{ 
      oneOf (roadUserCreator).create(); will(returnValue(createdRoadUsers)); 
      oneOf (anotherRoadUserCreator).create(); will(returnValue(moreCreatedRoadUsers)); 

      oneOf (createdRoadUsers).roadUsersAsList(); 
      oneOf (moreCreatedRoadUsers).roadUsersAsList(); 
     }}); 

     daemon.addRoadUserCreator(roadUserCreator); 
     daemon.addRoadUserCreator(anotherRoadUserCreator); 
     daemon.createRoadUsers(); 

     //how to easily check that the two lists are equivilant - have same items, but not the same object? 
     //assertEquals(createdRoadUsers, daemon.createRoadUsers()); 
    } 

    @Test 
    public void createsRoadUsersAccordingToCreator() throws Exception { 

     context.checking(new Expectations() {{ 
      oneOf (roadUserCreator).create(); will(returnValue(createdRoadUsers)); 
     }}); 
     assertEquals(createdRoadUsers, daemon.createRoadUsers(roadUserCreator)); 
    } 
} 

: 그럼 나는 창조자에 의해 반환 된 개별 컨테이너의 모든 요소와 컨테이너를 반환하는 경우 볼이 아닌 매개 변수화 createRoadUsers에 대한 테스트를 쓰기 시작 비 추악한 방법으로 진행하는 법을 확실히 이해하십시오.

'RoadUserContainer'인터페이스 :

public interface RoadUserContainer extends Iterable<RoadUser> { 
    public void add(RoadUser roadUser); 
    public Iterator<RoadUser> iterator(); 
    public void addAll(RoadUserContainer createRoadUsers); 
    public List<RoadUser> roadUsersAsList(); 
    public boolean equals(RoadUserContainer otherContainer); 
    ... 
} 

내가 TDD와 조롱에 새로운 오전, 이것은> 육년에 내 첫 자바 프로젝트이기 때문에 보조 미학에 대한 의견을 주시기 바랍니다!

답변

2

아마 실제 컨테이너를 사용하고 다른 객체를 조롱합니다. 그런 다음 hamcrest을 사용하여 결과 개체를 조사합니다.

나는 이런 식으로 뭔가 보일 것 만들 것입니다 시험 : 순서가 중요하지 않은 경우

import static org.hamcrest.MatcherAssert.assertThat; 
import static org.hamcrest.Matchers.contains; 

당신이 대신 containsInAnyOrder를 사용할 수 있습니다 : 당신이 hamcrest에서 이러한 수입이 필요합니다

final RoadUser roadUser0 = context.mock(RoadUser.class, "roadUser0"); 
final RoadUser roadUser1 = context.mock(RoadUser.class, "roadUser1"); 
final RoadUser roadUser2 = context.mock(RoadUser.class, "roadUser2"); 

final RoadUserCreator roadUserCreator0 = context.mock(RoadUserCreator.class, "roadUserCreator0"); 
final RoadUserCreator roadUserCreator1 = context.mock(RoadUserCreator.class, "roadUserCreator1"); 

final RoadUserCreationDaemon daemon = new RoadUserCreationDaemon(null); 
daemon.addRoadUserCreator(roadUserCreator0); 
daemon.addRoadUserCreator(roadUserCreator1);   

context.checking(new Expectations() {{ 
    oneOf(roadUserCreator0).create(); will(returnValue(roadUsers(roadUser0, roadUser1))); 
    oneOf(roadUserCreator1).create(); will(returnValue(roadUsers(roadUser2))); 
}}); 

assertThat(daemon.createRoadUsers(), contains(roadUser0, roadUser1, roadUser2)); 

을 contains

또한 유틸리티 메소드 "roadUsers"를 작성해야합니다.

public static RoadUserContainer roadUsers(final RoadUser... roadUsers) 
{ 
    return new RoadUserContainerImpl(roadUsers); 
} 

대안 설계는 다음이 같은 테스트를 쓸 수있는 RoadUserCreationDaemon

public void createRoadUsers(final RoadUserContainer roadUsers) { 
    for (final RoadUserCreator roadUserCreator : roadUserCreators) { 
     roadUsers.addAll(roadUserCreator.create()); 
    } 
} 

의 인터페이스를 변경하는 것입니다 :

final RoadUserContainer roadUserContainer0 = context.mock(RoadUserContainer.class, "roadUserContainer0"); 
final RoadUserContainer roadUserContainer1 = context.mock(RoadUserContainer.class, "roadUserContainer1"); 

final RoadUserContainer resultRoadUserContainer = context.mock(RoadUserContainer.class, "resultRoadUserContainer"); 

final RoadUserCreator roadUserCreator0 = context.mock(RoadUserCreator.class, "roadUserCreator0"); 
final RoadUserCreator roadUserCreator1 = context.mock(RoadUserCreator.class, "roadUserCreator1"); 

final RoadUserCreationDaemon daemon = new RoadUserCreationDaemon(null); 
daemon.addRoadUserCreator(roadUserCreator0); 
daemon.addRoadUserCreator(roadUserCreator1); 

context.checking(new Expectations() { 
    { 
     oneOf(roadUserCreator0).create(); 
     will(returnValue(roadUserContainer0)); 
     oneOf(roadUserCreator1).create(); 
     will(returnValue(roadUserContainer1)); 

     oneOf(resultRoadUserContainer).addAll(roadUserContainer0); 
     oneOf(resultRoadUserContainer).addAll(roadUserContainer1); 
    } 
}); 

daemon.createRoadUsers(resultRoadUserContainer); 

만약을에 대한 호출의 순서 "addAll"은 매우 중요합니다. jmock sequence

1

나는 창조주를 조롱 하겠지만 진짜 용기를 돌려 주었다고 생각합니다. 테스트의 아이디어는 데몬이 모든 작성자의 작성 메소드를 호출했는지 확인하는 것입니다. 맞습니까? 따라서 테스트 조건은 다음과 같을 것입니다

+0

컨테이너가 '값'객체로 남아있게하려면 실제 컨테이너를 만드는 것이 좋습니다. – neuronotic

+0

값 오브젝트 일 필요는 없습니다. 데몬이 작성한 컨테이너에 2 개의 작성자 오브젝트가 작성한 모든 사용자가 들어 있는지 확인하십시오. 말이 돼? – jeff

+0

그래, 나는 이해했다고 생각한다. - 그리고 그것은 현재 내가 어떻게 진행 했는가이다 (고맙다;)). 그러나, 그것은 여전히 ​​다른 객체의 실제 구현에 연결하는 약간의 냄새를 남기는 것처럼 보입니다. 나는 대답에 대해 찬성표를 던졌지 만, 나는 하루나 이틀 동안 답변을 표시하지 않도록 할 것이다. – neuronotic

관련 문제