2008-09-04 9 views
8

그래서 Google 테스트 블로그를 읽었으며 글로벌 상태가 좋지 않으며 테스트를 작성하기가 어렵다고 말합니다. 나는 그것을 믿는다 - 나의 코드는 지금 테스트하기가 어렵다. 그렇다면 지구 적 국가를 어떻게 피할 수 있습니까?어떻게 전역 상태를 피할 수 있습니까?

내가 이해하는대로 전역 상태를 사용하는 가장 큰 일은 개발, 수용 및 프로덕션 환경간에 주요 정보를 관리하는 것입니다. 예를 들어, "Globals"라는 정적 클래스에 "DBConnectionString"이라는 정적 멤버가 있습니다. 응용 프로그램이로드되면로드 할 연결 문자열을 결정하고 Globals.DBConnectionString을 채 웁니다. 파일 경로, 서버 이름 및 기타 정보를 Globals 클래스에로드합니다.

내 기능 중 일부는 전역 변수를 사용합니다. 따라서 함수를 테스트 할 때 특정 전역 변수를 먼저 설정해야합니다. 그렇지 않으면 테스트가 실패합니다. 나는 이것을 피하고 싶다.

상태 정보를 관리하는 좋은 방법이 있습니까? (또는 전역 상태를 잘못 이해하고 있습니까?)

답변

10

의존성 주입이 당신이 찾고있는 것입니다. 이러한 함수를 사용하지 않고 종속성을 찾으려면 종속성을 함수에 주입하십시오. 즉, 함수를 호출 할 때 원하는 데이터를 전달합니다. 그렇게하면 적절한 곳에 모의 객체를 삽입 할 수 있기 때문에 클래스 주위에 테스트 프레임 워크를 두는 것은 쉽습니다.

일부 글로벌 상태는 피하기 어렵지만 가장 좋은 방법은 응용 프로그램의 최상위 수준에서 팩토리 클래스를 사용하는 것입니다. 맨 아래 수준의 모든 것은 종속성 주입을 기반으로합니다.

두 가지 주요 이점 : 하나는 테스트가 훨씬 쉽고 두 가지는 느슨하게 결합 된 것입니다. 당신은 구현보다는 클래스의 인터페이스를 상대로 프로그램 할 수있는 것에 의존합니다.

1

위대한 첫 번째 질문입니다.

짧은 답변 : 응용 프로그램이 모든 입력 (암시 적 입력 포함)에서 출력까지의 기능인지 확인하십시오.

설명하는 문제가 글로벌 상태가 아닌 것 같습니다. 적어도 변경 가능한 상태는 아닙니다. 오히려 당신이 묘사하는 것은 종종 "구성 문제"라고 불리는 것 같이 보이며 많은 해결책이 있습니다. Java를 사용하는 경우 Guice과 같은 경량 주입 프레임 워크를 조사 할 수 있습니다. 스칼라에서는 대개 implicits으로 해결됩니다. 일부 언어에서는 다른 프로그램을로드하여 런타임에 프로그램을 구성 할 수 있습니다. 이것은 스몰 토크로 작성된 서버를 구성하는 방법이며, 설정 파일이 하스켈 프로그램 중 하나 인 Xmonad라는 하스켈로 작성된 윈도우 관리자를 사용합니다. 당신의 검사 결과가 통합 테스트보다는 장치가을 테스트 무엇 당신이하고있는 그런 다음 데이터베이스 나 파일 시스템과 같은 실제 자원을 포함하는 경우

2

명심하십시오. 통합 테스트는 예비 테스트를 필요로하는 반면 단위 테스트는 독립적으로 실행할 수 있어야합니다.

당신은 성 윈저 같은 있지만 같은 도로 접근의 중간을 할 수 있습니다 간단한 경우에 대한 종속성 주입 프레임 워크의 사용으로 볼 수 있었다 : 당신이 가장 것 현실에서

public interface ISettingsProvider 
{ 
    string ConnectionString { get; } 
} 

public class TestSettings : ISettingsProvider 
{   
    public string ConnectionString { get { return "testdatabase"; } }; 
} 

public class DataStuff 
{ 
    private ISettingsProvider settings; 

    public DataStuff(ISettingsProvider settings) 
    { 
     this.settings = settings; 
    } 

    public void DoSomething() 
    { 
     // use settings.ConnectionString 
    } 
} 

가능성이 귀하의 구현에서 구성 파일에서 읽을 수 있습니다.만약 당신이 그것을 위해, 스왑 구성을 가진 전체 날려 DI 프레임 워크 갈 방법이지만 적어도 Globals.ConnectionString 사용하는 것이 좋습니다 생각합니다.

0

MVC 속에서 의존성 주입의 예 간다 :

의 index.php

$container = new Container(); 
include_file('container.php'); 

container.php

container.add("database.driver", "mysql"); 
container.add("database.name","app"); 

...

$container.add(new Database($container->get('database.driver', "database.name")), 'database'); 
$container.add(new Dao($container->get('database')), 'dao'); 
$container.add(new Service($container->get('dao'))); 
$container.add(new Controller($container->get('service')), 'controller'); 

$container.add(new FrontController(),'frontController'); 

index.php가 계속됩니다.

$frontController = $container->get('frontController'); 
$controllerClass = $frontController->getController($_SERVER['request_uri']); 
$controllerAction = $frontController->getAction($_SERVER['request_uri']); 
$controller = $container->get('controller'); 
$controller->$action(); 

과 거기에 당신이 그것을 가지고는, 컨트롤러가 에 의존하는 서비스 계층 개체에 따라 달라 데이터베이스 드라이버를 따라와 데이터베이스 오브젝트에 의존하는 DAO (데이터 액세스 개체) 개체 이름의 등

관련 문제