NUnit으로 ActiveX 컨트롤을 테스트하는 방법

NUnit을 좀 더 일반적으로 사용하기 위해서 꼭 짚고 넘어가야 할 부분이 하나 있습니다. 바로 NUnit GUI와 Windows Forms의 ActiveX Interop 기능 사이의 충돌입니다. 그저 다음처럼 코드를 작성하고 테스트를 실행하게 되면 “빨간 막대”를 만납니다.

[CODE]
[Test]
public void Test()
{
  Form f = new Form();
  f.Controls.Add(new WebBrowser());
  f.ShowDialog();
}
[/CODE]

NUnit GUI는, 아직 자세히 살펴보지는 않았지만, 모든 실행 루틴을 다중 스레드에 의하여 실행하는 것처럼 보입니다. 위와 같은 테스트 코드는 빨간 막대를 만나지만 결코 의미있는 빨간 막대가 될 수 없습니다. 왜냐면, 아무런 진행이 되지 않기 때문이죠. 구체적으로, 위와 같은 코드를 NUnit GUI 상에서 실행하게되면, ActiveX 컨트롤의 인스턴스를 스레드 모델 규정에 따르자면 만들 수 없다는 이야기를 하게 됩니다. 그러면, 방법이 없는걸까요? 아닙니다! 아래 코드는 .NET Framework 2.0을 기준으로 설명하는 것입니다.

[CODE]
[Test]
public void Test()
{
  Thread t = new Thread(delegate (object o)
  {
       Form f = new Form();
       f.Load += new new EventHandler(m_oTestForm_Load);
       Application.Run(f);
  }

  t.TrySetApartmentState(ApartmentState.STA);
  t.Start(null);
  t.Join();
}

private void m_oTestForm_Load(object sender, EventArgs e)
{
  Form f = (Form)sender;
  f.Controls.Add(new WebBrowser());
}
[/CODE]

이처럼 코드를 고치면 Windows Forms의 스레드는 NUnit GUI의 스레드가 아닌 새로운 스레드에서 인스턴스를 만들게 되며, 이 때 만난 새로운 스레드는 STA 모드이므로 Windows Forms를 비롯하여 Web Browser 컨트롤이 정상적으로 생성될 수 있는 환경이 됩니다. 그리고 NUnit GUI가 실행하게될 테스트 메서드의 마지막에 위치한 Join 메서드로 폼이 닫히기 전까지 테스트를 동결시킬 수 있습니다. 만약, 동결이 필요하지 않다면 Join 메서드를 사용하지 않으면 되겠지요. 🙂

댓글 남기기