2012-01-06 3 views
1

내가 만드는 Windows Forms 응용 프로그램에 문제가 있습니다. 응용 프로그램은 통합 테스트 응용 프로그램으로 간주됩니다. 본질적으로, 그것은 내 수업 중 하나에서 많은 웹 서비스를 이용하는 메소드를 테스트하기로되어 있습니다. 난 반사를 통해 테스트 할 클래스의 방법을로드하고,이 같은 일을 오전 :이 웹 서비스와 장소를 테스트하기 위해 생성 된 클래스에서 메소드의 목록을 반환ListBox에서 선택한 메서드 호출

private List<string> GetMethods(Type type) 
{ 
    return (from method in type.GetMethods() where method.IsPublic && 
     method.ReturnType == typeof(void) select method.Name).ToList(); 
} 

ListBox에서 사용자가 원하는만큼 많은 메서드를 선택할 수 있습니다. 내 혼란이 여기에옵니다. 내가하고 싶은 것은 사용자가 선택한 메소드를 얻고 해당 메소드 X 번을 실행하는 것입니다 (폼에 메소드를 실행하는 횟수를 입력하는 텍스트 상자가 있습니다). 리플렉션을 통해 얻은 메서드 이름을 기반으로 이러한 메서드를 실행하는 방법을 파악할 수 없습니다. 나는 이런 식으로 뭔가를 시도했습니다,하지만 난 그게 옳지 않아 아는이도 컴파일되지 않습니다

private void RunMethods(Type type) 
{ 
    var tester = new ClassToTest(); 
    foreach(var item in lstMethodList.SelectedItems) 
    { 
     foreach(var method in type.GetMethods()) 
     { 
      if(String.Equals(item.ToString(), method.Name)) 
      { 
       ThreadStart ts = new ThreadStart(method.Name); 
       Thread thread1 = new Thread(ts); 
       thread1.Start(); 
      } 
     } 
    } 
} 

하는 ThreadStart 매개 변수로 메서드 이름을 필요로한다. 이것이 가능한 방법이 있습니까? 어쩌면 논리적으로 잘못 될 것 같지만, 사용자가 지정하는 여러 번 실행하고 실행해야하는 각 메소드에 대한 스레드를 만들고 싶습니다. 이것은 웹 서비스가 처리 할 수있는 것을보기 위해 일부로드 테스트와 함께 통합 테스트를 수행하는 방법으로되어 있습니다.

+0

Google로 검색하는 것이 도움이되지 않았습니까? http://www.codeproject.com/KB/cs/C__Reflection_Tutorial.aspx – Zenwalker

+0

정적 또는 인스턴스 메서드라고 부르는 메서드가 있습니까? –

+0

그들은 모두 호출하려고하는 인스턴스 메서드입니다. 나는 내가 잘못하고 있다고 생각하기 시작했다. 왜냐하면 나는 메소드를 얻는 클래스가 내가 테스트하기를 원하는 클래스 인 _tests_ 클래스이기 때문이다 ... 그래서 아마도 나는 클래스 자체 테스트해야합니다. – Zajn

답변

0

Activator을 사용하여 클래스의 인스턴스를 만들 수 있습니다.

그런 다음 Invoke을 사용하여 메소드 중 하나를 호출 할 수 있습니다.이 같은

뭔가 작업을해야합니다 :

내가 테스트중인 클래스를 가정 한
private void RunMethods(Type type) 
{ 
    foreach(var item in lstMethodList.SelectedItems) 
    { 
     foreach(var method in type.GetMethods()) 
     { 
      if(String.Equals(item.ToString(), method.Name)) 
      { 
       MethodInfo capturedMethod = method; 
       var t = new Thread(() => ThreadMain(type, capturedMethod)); 
       t.Start(); 
      } 
     } 
    } 
} 

static void ThreadMain(Type type, MethodInfo mi) 
{ 
    object o = Activator.CreateInstance(type); 

    object[] parameters = new object[] { }; 

    mi.Invoke(o, parameters); 
} 

는 매개 변수가없는 생성자가 있습니다.

+0

예, 테스트중인 클래스에는 매개 변수가없는 생성자가 있습니다. 비록 내가 그것을 생각하면, 나의 수업은 조금 복잡하게 설정되어 있지만. 나는 테스트하고 싶은 클래스를 테스트하기위한 단위 테스트를 가진 클래스를 가지고 있는데,이 Windows Form으로부터 그 단위 테스트 클래스를 호출하려고한다. 최종 제품에서 그렇게하고 싶지는 않지만 지금 Windows Form에서 메서드를 실제로 호출 할 수 있는지 테스트하기 위해 노력하고 있습니다. 나는 단위 테스트보다는 통합 테스트가 필요한 다른 클래스가 필요할 것이라고 생각합니다. – Zajn

+0

나는 지금 이것을 지금 시험해 보았고, 나는 그것이 올바른 길에 있다고 생각한다. 감사 니콜라스! – Zajn

1

당신은 당신이 원하는 방법을 얻기 위해이 같은 것을 사용할 수 있습니다 : 당신은 (방법은 정적 경우에만 작동합니다) 당신이 쓰는 것 별도의 스레드에서 메서드를 호출 할 경우

private List<MethodInfo> GetMethods(Type type) 
{ 
     return (from method in type.GetMethods() 
       where method.IsPublic && 
        method.ReturnType == typeof(void) 
       select method).ToList(); 
} 

을 :

foreach(MethodInfo mi in GetMethods(SomeType) { 
    MethodInfo tempMi = mi; 
    Action myAction = (Action) Delegate.CreateDelegate(typeof(Action), tempMi); 
    ThreadStart ts = new ThreadStart(myAction); 
    Thread thread1 = new Thread(ts); 
    thread1.Start(); 
} 

아니면 쓸 것 (방법은 매개 변수를 취할 수있다 상속 방법 조심 엄격히 매개 변수가없는 경우에만!) :

foreach (MethodInfo mi in GetMethods(type)) 
{ 
    MethodInfo tempMi = mi; //modified closure 
    object o = Activator.CreateInstance(type); 
    Action myAction = delegate() { tempMi.Invoke(o, null); }; 
    ThreadStart ts = new ThreadStart(myAction); 
    Thread thread1 = new Thread(ts); 
    thread1.Start(); 
} 

메서드가 매개 변수를 사용하는 경우 그에 따라 null (Invoke 메서드에서 현재 MethodInfo에서 호출 됨) 대신 개체 배열 (object [] { ... })을 전달해야합니다. 물론 배열의 객체를 수정합니다.

실제로 Thread List를 가져 와서 목록의 각 MethodInfo에 대해 새 Thread를 추가하면 나중에 제어 할 수 있습니다 (예 : 중지하려는 경우). HashMap 또한 좋은 선택이 될 것입니다. 핵심은 MethodInfo 또는 Action이고 값은 연관된 Thread입니다.

+0

이것은 유망 해 보이지만, 코드를 변경했기 때문에 런타임에 "대상 메서드에 오류 바인딩"오류가 발생합니다. 이것은 내 코드의 오류가 아닌 다른 곳의 오류 일 수 있습니다. – Zajn

+1

당신은 메소드가 정적이라고 가정했습니다. –

+0

아마도 여기에는 액션 유형을 사용하기 때문에이 코드를 사용하지 않아도 테스트 된 메소드에 인수가 포함되어있을 수 있습니다. @ NicholasButler 편집이 맞습니다. – Max

0

MethodInfos 및 메서드 이름을 포함하는 개인 사전을 구현할 수 있습니다.

private Dictionary<string, MethodInfo> methodList; 
     private List<string> GetMethods(Type type) 
     { 
      methodList = new Dictionary<string, MethodInfo>(); 

      type.GetMethods().Where(m=>m.IsPublic && m.ReturnType.Equals(typeof(void))).ToList().ForEach(m=> 
       methodList.Add(m.Name,m) 
       ); 

      return methodList.Keys.Select(k => k).ToList(); 
     } 

드롭 다운 선택시 사전에서 메소드를 찾아 실행할 수 있습니다.

관련 문제