2009-09-21 4 views
3

최근 특수 형식의 파일에서 데이터베이스로 데이터를 가져올 수있는 간단한 유틸리티를 만드는 작업이 있습니다. 몇 가지 클래스 (프로그램 클래스는 비즈니스 로직 클래스와 함께 작동하며, 비즈니스 로직 클래스는 데이터 액세스 클래스로 작동 함)로 콘솔 애플리케이션을 구현했습니다. 모든 것은 정상적으로 작동하지만, 지금은 단위 테스트와 리팩토링 애플리케이션을 만드는 것에 대해 생각하고 있습니다. (이전에 실제 단위 테스트를 작성하지 않았고 오랜 시간 전에 통합 테스트를 한 번도하지 않았기 때문에이 애플리케이션은 실전을위한 완벽한 분야라고 생각합니다) .데이터 액세스, 유닛 테스트, 종속성 삽입

그래서 여기에 문제가 있습니다. 데이터 액세스 클래스가 정적으로 만들어졌으며,이를 조롱하거나 실제 단위 테스트를 만들 수 없습니다. 이 문제를 해결하려면 인터페이스를 만들고 데이터 액세스 클래스에서 구현해야합니다. 또한 해당 인터페이스 형식의 매개 변수를 받아들이는 비즈니스 논리 클래스에 생성자를 추가해야합니다. 그래서 이것은 응용 프로그램 Main() 메소드에서 데이터 액세스 클래스를 작성하게 될 것이고 어떤 것이 가장 좋은 방법이 아니라는 것을 알려줍니다 (엔트리 포인트가 일부 데이터 액세스에 대해 알아야합니다.) 체인이 훨씬 길거나 몇 개의 사슬이 있어야합니까?). 몇 가지 IoC 컨테이너를 사용할 수는 있지만 컨테이너를 사용하는 것은 너무 간단한 응용 프로그램이라고 생각합니다.

감사합니다.

답변

5

내가 인터페이스를 생성하고 데이터 액세스 클래스를 구현해야합니다. 또한 해당 비즈니스 로직 클래스에 이라는 생성자를 추가해야합니다. 해당 인터페이스의 매개 변수를 수락합니다. 유형입니다.그래서 내가 응용 프로그램 main() 메소드에서 데이터 액세스 클래스를 만드는 최대 종료됩니다 것을 의미 뭔가 나에게이되지 최고의 방법 (가 진입 점 일부에 대한 데이터 액세스 것을 알아야 정말 괜찮 알려줍니다 ? 체인 가 더 이상 경우, 또는 여러 체인?) 반대로

이 있어야 무슨! 이 은 최소한 테스트 가능성 관점에서 보면 가장 좋은 접근 방식 인입니다.

비즈니스 논리 계층을 테스트 할 수있게 만드는 유일한 방법은 고려중인 작업을 정확하게 수행하여 데이터 액세스 계층에서 데이터를 격리하는 것입니다.

귀하의 최상위 응용 프로그램은 불행이 멈추는 곳입니다. 구체적인 데이터 액세스 클래스가 무엇인지 알아야하는 유일한 구성 요소입니다.

체인이 훨씬 길거나 체인이 여러 개인 경우 문제가되지 않습니다 (일부 응용 프로그램 레이어가 붕괴되는 경우 고려해야 할 수도 있음). 이 잠재적 인 코드를 살펴 보자 (또한 Repository에 의존)을 AccountingServiceRepository에 대한 종속성과 의존성이있는 PresenterCustomerService에 대한 종속성이있는 Model-View-Presenter 응용 프로그램의 View, :

public CustomerView() { 
    IRespository  repository  = new ConcreteRepository(); 
    IAccountingService accountingService = new ConcreteAccountingService(repository); 
    ICustomerService customerService = new ConcreteCustomerService(accountingService, repository) 
    this._Presenter = new CustomerPresenter(customerService); 
} 

을 마지막으로, 원하지 않는 경우 의존성 주입 컨테이너를 사용할 필요가 없습니다 (일부는 놀라 울 정도로 가벼우 긴하지만). - 직접 의존성 주입을 사용하면 자신을 반복해서 시작할 때까지 잘 작동합니다. 런타임시 종속성).

+0

+1 : 좋은 답변입니다! 나는 특히 "벅이 멈추는 곳"을 좋아한다.DI 컨테이너에 대한 좋은 의견도 있습니다! – TrueWill

+0

@ 제프 - 고마워요, 한번 시도해 보겠습니다. 내 비관적 인 존재가 몇 가지 숨겨진 함정이 있어야한다고 말하지만 : – Dev

+0

@Dev : 회의론은 경건의 옆에있다! ;) –

0

여기에 간단한 솔루션입니다 :

public void insert (...) { 
     DataAccess.insert (...); 
    } 

지금 당신이 이러한 호출을 무시할 수 있습니다 : 대신에 직접 데이터 액세스 클래스를 사용 헬퍼 메소드를 호출. 그래서 같이 테스트를 분할하는 것이 좋습니다 :

  1. DataAccess가 올바른 매개 변수를 가져 옳은 일을한다는 것을 확인 시험의 몇 가지를 만듭니다.

  2. 실물 크기 테스트에서 으로 전송 된 매개 변수를 수집하기 만하면됩니다. DataAccess으로 전화하지 마십시오. # 1

시험은 # 2에서 테스트가 올바른 값으로 DataAccess를 호출해야 할 것입니다 동안 DB에 데이터를 기록하는 작동하는지 확인합니다. 후자의 테스트는 매우 빨리 실행되므로 특별한 경우 등을 쉽게 테스트 할 수 있습니다.

항상 1 번에서 테스트를 실행할 필요는 없습니다. DataAccess 또는 릴리스 전에 무언가를 변경할 때만 가능합니다. 그러면 테스트가 효율적이고 즐겁습니다.

+0

답변으로 덧글을 추가했습니다. 별다른 공간이 없었습니다 – Dev

+0

@Dev - 답변으로 응답하면 혼란 스러울 수 있습니다. 결국 대답은 다시 주문되며, Aaron은 그의 이름을 바꿀 수도 있고 심지어 그의 대답을 삭제할 수도 있습니다. 나는 코멘트에 답할 것을 권한다. 할당 된 캐릭터보다 더 많은 공간이 필요하다면, 두 가지 코멘트에 걸쳐 응답을 분산시킬 수있다. 또는 원래 질문을 편집하여 사람들이 귀하에게 대답하는 데 도움이된다고 생각되면 일부 정보를 포함 할 수 있습니다. –

+0

감사합니다. Jeff 님,이 "답변"을 댓글로 옮깁니다. – Dev

1

LINQ to SQL을 사용한다고 가정하면 나중에 저장소 패턴을 사용하여 DataContext를 나중에 조롱 할 수있는 인터페이스로 래핑하여 단위 테스트를 수행 할 수 있습니다.

여기에 하나, 인터넷의 주위에이 주제에 대한 몇 가지 기사가 있습니다 http://andrewtokeley.net/archive/2008/07/06/mocking-linq-to-sql-datacontext.aspx

+0

지금은 파일에서 읽고 파일에 쓰는 사용자 지정 메서드로 형식화 된 데이터 집합을 사용하고 있습니다. 엔티티 프레임 워크 나 linq2sql을 처음에는 사용하지 않았습니다. 왜냐하면이 응용 프로그램을 작성해야 할 당시 경험하지 못한 기술에 대한 실험을 할 시간이별로 없었기 때문입니다. 그러나 이것은 좋은 생각입니다. DAL. – Dev