2009-09-17 5 views
6

테스트 사례를 구성 할 수 있도록 종속성 주입 패턴을 사용하여 DefaultController라는 MVC 기본 컨트롤러를 구현했습니다. 예 아래 : 다음테스트 목적으로 기본 컨트롤러 종속성 주입을 해결하는 방법은 무엇입니까?

public class DefaultController : Controller 
{ 
    protected readonly ISessionHelper _sessionHelper; 
    string _thisUserOpenID; 
    protected IUsersRepository _UserRepository; 
... 
    public DefaultController() 
    { } //not for testing 

    public DefaultController(ISessionHelper session, IUserRepository repo) 
    { 
     _sessionHelper=session; 
     _UserRepository = repo; 
    } 
} 

나는 상황에서 자신을 발견 몇 가지 테스트 케이스를 구축, 지금은 내 등이 컨트롤러, homecontroller, usercontroller를 사용하여 컨트롤러,

을하는 것은 내가 모르는 경우 어떻게 사실로 주입 의존성 패턴을 사용하십시오.

[TestMethod] 
    public void Welcome_Message_In_ViewData_Has_Coockie_User_Display_Name() 
    { 
     // Below I want to insert FakeRepositories using 
     //ISessionHelper and so on. but the constructor 
     //for homecontroller don't have it. 
     HomeController controller = new HomeController(); 

아이디어가 있으십니까?

답변

5

당신의 HomeController는 기본 생성자를 호출하는 "injectable"일치하는 생성자를 가져야합니다.

public HomeController(ISessionHelper session, IUserRepository repo) 
    : base(session, repo) 
    { 

    } 

이제 테스트에서 해당 생성자를 사용하여 HomeController를 만들고 조롱 된 세션 및 사용자 저장소를 전달합니다. 조롱에 관해서는 많은 인기있는 조롱 프레임 워크 용 코드 인 Scott Hanselman's MvcMockHelpers classes에도 관심이있을 수 있습니다.

3

왜 생성자가 두 개인지 알 수 없습니다. 매개 변수가없는 생성자를 없애면됩니다. Castle Windsor와 같은 DI 프레임 워크 또는 필자가 선호하는 AutoFac을 사용하면이 모든 작업을 처리 할 수 ​​있습니다. 그렇다면 테스트와 관련하여 Moq와 같은 것을 사용하십시오. 즉

public DefaultController(ISessionHelper session, IUserRepository repo) 
{ 
    _sessionHelper = session; 
    _UserRepository = repo; 
} 

DI 프레임 워크로 DefaultController, ISessionHelper 및 IUserRepository를 등록하십시오. 의 라인을 따라 뭔가 :

Register(new DefaultController()); (it is something like that in Autofac) 
Register<SessionHelper>().As<ISessionHelper>(); 
Register<UserRepository>().As<IUserRepository>(); 

그런 식으로, 당신은 컨테이너에서 DefaultController를 당길 수 있고, DI 프레임 워크는 당신을 위해 두 개의 매개 변수를 삽입합니다. 내 DI 컨테이너에 액세스하기 위해 정적 메소드를 마무리하면 다음과 같이 보입니다.

var controller = IoC.Resolve<DefaultController>(); 

기본적으로 Autofac으로 넘어 가서 살펴 봅니다. 컨트롤러를 등록 할 수있는 웹 모듈도 있습니다.

그런 다음 테스트하려면 Moq을 사용하거나 "AutoMocker"(google it) 형식을 찾아야합니다. 나는 할 것이다 :

var session = new Mock<ISessionHelper>(); 
var repo = new Mock<IUserRepository>(); 
repo.Setup(s => s.FindById(123)).Returns(new User()); 

var conroller = new DefaultController(session.Object, repo.Object); 
controller.Execute(); 

또한 ewwwrepositories. 닷넷과 제네릭 등 ... 그냥 좋은 자신을 만들 수 있습니다.

var session = IoC.Resolve<ISession>(); 
var user1 = session.Get<User>(123); 
var user2 = session.Get<User>(u => u.Username == "admin"); 
session.Update(user3); 

한 가지만 전달하면 무엇이든 사용할 수 있습니다. 때때로 많은 저장소를 전달해야하는 것보다. 또한 Unit of Work 패턴을 멋지게 설정합니다.

+0

참고로 매개 변수없는 생성자를 없애면 컨트롤러 팩토리를 롤업해야합니다. – womp

+0

왜 공장인가? 위의 경우 DI 프레임 워크가 모든 것을 주입합니다. ISessionHelper 및 IUserRepository 같은 것들은 정적 세션을 벗어나서 전달하려는 값이 없을 것입니다. var controller = IoC.Resolve () ; 그리고 그것은 모두 당신을 위해 지어졌습니다. 생성자를 통해 주입한다는 것은 메소드 params를 통해 변수를 전달하거나 공용 속성을 설정해야한다는 것을 의미합니다 (Command 패턴과 비슷 함). – Bealer

관련 문제