티스토리 툴바


몇일 전부터 MSDN사이트가 정상적으로 열리지 않는 현상이 있었습니다. 저는 IE와 크롬을 사용하는데 둘 다 동일하게 발생하는 현상입니다. 그래서 검색을 해봤는데 인터넷 정보 삭제를 하면 된다는 글을 보고 삭제를 하니 정상적으로 MSDN 사이트가 보이는 듯 싶었습니다. 그래서 해결이 되었구나 싶었는데 검색을 한 이후에 검색 결과를 선택하고 나면 이전과 동일하게 아래의 메세지를 보여주었습니다.

 The specified CGI application encountered an error and the server terminated the process.

그래서 다시 검색을 해보았지만 별다른 해결책은 없어 보였습니다. 검색 중에 짧게 쿠키 때문이라는 말이 보여서 크롬에서 먼저 아래와 같이 쿠키 설정을 해보았습니다.

크롬

옵션 -> 고급설정 -> 콘텐츠 설정 -> 쿠키(예외관리)


위의 그림과 같이 msdn사이트에 대한 쿠키 쓰기를 차단해주었더니 해결이 되었습니다.
이미 저장된 쿠키가 있을 수도 있기 때문에 인터넷 사용정보 삭제(전체)를 하신 후에 하시면 됩니다.

IE
먼저 아래와 같이 인터넷 사용정보를 삭제해주세요.
도구 -> 인터넷 옵션 -> 일반탭 ->  검색기록(삭제)


여기서 중요한 것은 즐겨찾기 웹 사이트 데이터 보존에 체크를 해제하셔야 합니다. 이게 안되면 MSDN 첫 페이지가 제대로 열리지 않습니다. 그리고 난 이후에 쿠키에 대한 설정을 아래와 해주시면 됩니다.

도구 -> 인터넷 옵션 -> 개인 정보 탭 -> 사이트


MSDN 사이트를 차단해야 MSDN에서 검색을 할 수 있다니. --;;
여튼 이 모든게 MS 때문인 것으로 보입니다. ^^; 



 
저작자 표시 비영리 변경 금지
Posted by resisa
ASP.NET MVC3에 대한 자세한 소개는 아래의 링크로 대신합니다.
http://www.asp.net/mvc/mvc3#overview

가장 큰 변화는 아무래도 Razor View 엔진이겠죠? 처음에는 무슨 또 새로운 엔진이야 싶었는데 특별히 배우지 않고서도 동일한 코드를 간단하게 작성할 수 있네요.

아래의 튜토리얼을 쭉 보다가 샘플을 하나 다운로드 받아서 보았는데 괜찮네요.
http://davidhayden.com/blog/dave/archive/2011/01/05/ASPNETMVC3TutorialsIndex.aspx

Projet Silk라는 샘플인데 Pattern & Practice 팀에서 만든 거라 그런지 아키텍처 구성도 좋네요.
특히 Script 관련 테스트 방법과 구조는 완전 맘에 드네요.
jQuery 테스트에는 qunit이 사용되었고 일반적인 테스트 코드에는 xunit를 사용하였습니다.
xunit에서 눈에 확 들어오는 장점은 아무래도 MSBuild와 연계하여 테스트를 하는 것이 아닐까 싶습니다.
아래는 비교 링크입니다.
http://xunit.codeplex.com/wikipage?title=Comparisons&referringTitle=Home
여튼 테스트 코드를 살펴보면 웹 프로젝트에서는 테스트 코드를 어떻게 작성하는지에 대한 충분한 힌트를 얻을 수 있을 것입니다.
저작자 표시 비영리 변경 금지
Posted by resisa

Rhino Mocks 기본편

Framework 2011/05/24 17:34
이전에 Mocking Framework로 Rhino Mocks에 대하여 링크로 간단한 소개글을 썼었습니다. 본 글에서는 Mocking Framework는 왜 필요한지와 Rhino Mocks에 대한 Practice에 대하여 설명하고자 합니다.

먼저 아래의 간단한 코드로 시작합니다.
[TestMethod]

public void GenerateMock_Vs_GenerateStub()

{

    // 1. GenerateStub

    var stubRepository = MockRepository.GenerateStub<IRepository>();

 

    stubRepository.Property = 1;

    Assert.AreEqual(stubRepository.Property, 1);

 

    // 2. GenerateMock

    var mockRepository = MockRepository.GenerateMock<IRepository>();

 

    mockRepository.Property = 1;

    Assert.AreEqual(mockRepository.Property, 0);

 

    mockRepository.Stub(t => t.Property).Return(1);

    Assert.AreEqual(mockRepository.Property, 1);

}

=> Rhino Mocks에서는 MockRepository라는 클래스를 사용하여 가짜 개체를 만들어 주는 것을 볼 수 있습니다. 가짜 개체를 만들 때에 대상이 되는 타입은 인터페이스입니다. 특정 타입이 아닌 인터페이스를 통해서 가짜 개체를 만들어주고 있습니다. 바로 여기서 Mocking Framework를 사용하는 한 가지 이유가 보입니다. 화면과 통신을 각각 담당하여 개발을 한다고 하면 화면을 담당하는 개발자는 통신을 담당하는 개발자가 모든 개발을 하기 전까지 화면에 통신 데이타를 보여주지 못할 것입니다. 하지만 이렇게 인터페이스와 Mocking Framework를 사용한다면 통신 개발이 완료되지 않았다고 하더라도 데이터를 보여줄 수 있습니다. 어떻게? (물론 실제 통신 클래스에서 가짜 데이터를 만들어서 넣어줘도 화면에 보여줄 수는 있습니다.) 바로 위의 코드에 답이 있습니다. StubRepository는 바로 Property라는 이름의 프로퍼티에 값을 할당하는 것으로 MockRepository는 Stub() 메서드를 사용하여 값을 할당하는 방법입니다. Stub과 Mock의 사용 방법에 대한 차이는 알겠는데 실질적으로 어떠한 상황에서 Stub을 또는 Mock를 사용해야 하는 걸까요?

[TestMethod]

public void The_Difference_Between_Stubs_And_Mocks()

{

    var repository = MockRepository.GenerateMock<IRepository>(); 

    // MockRepository.GenerateStub<IRepository>();

 

    var user = new User { Name = "Old User" };

 

    repository.Stub(t => t.GetUser("Old User")).Return(user);

 

    repository.Expect(t => t.Save(user));

 

    var controller = new LoginController(repository);

    controller.ChangeUserName("Old User");

 

    repository.VerifyAllExpectations();

}

=> 먼저 Mock(GenerateMock()메서드 사용)은 위의 Expect()메서드와 같이 실행이 예상되는 메서드를 지정하고 마지막 줄의 VerifyAllExpectatation()로 검증 작업을 합니다. 여기서 검증 대상이 되는 실질적인 클래스는 어떤 것일까요? 바로 LoginController입니다. 해당 코드 중에 new키워드를 사용하여 인스턴스화 한 클래스는 User와 LoginController입니다. Rhino Mocks에서는 바로 이렇게 실질적으로 인스턴스화 한 클래스에서 검증을 합니다. 해당 내용은 마지막 부분에서 Event와 관련된 코드에서 다시 한 번 살펴보도록 하겠습니다.
그러면 검증 대상이 된 LoginController는 어떻게 구현이 되어 있는지 살펴보겠습니다.
public class LoginController
{
    IRepository repository;

    public LoginController(IRepository repository)
    {
        this.repository = repository;
    }

    public void ChangeUserName(string userName)
    {
        var user = repository.GetUser(userName);

        user.Name = "New User";
        repository.Save(user);
    }
}
=> 위의 테스트 코드를 실행시키면 Pass가 됩니다. 주석 처리된 부분을 Stub으로 변경하여도 Pass가 됩니다. 그렇다면 차이점이 없는 것일까요? LoginController에서 Save()메서드가 호출되는 부분을 주석처리 하고 Stub 테스트 코드를 실행하면 오류가 발생하지 않습니다. 정리하면 Expect()메서드로 호출될 것이라 예상된 메서드가 실행이 되든 되지 않든 Pass가 된다는 말입니다. Mock의 경우에는 Fail이 발생합니다. 이것으로 둘의 차이점과 언제 Mock을 언제 Stub을 사용해야 할지를 판단할 수 있습니다. Expect()메서드를 사용 유무로 또한 차이점이기는 하지만 해당 Expect()메서드는 Rhino Mocks에서 제공하는 메서드일 뿐입니다.(아래의 참고 링크를 보시면 Stub에서도 호출 여부를 판단할 수 있는 방법도 존재합니다.) Stub으로 만드는 개체의 경우에는 해당 개체의 행위 또는 값이 해당 테스트 코드와의 상관없거나 영향을 미치지 않는 개체일 경우에 사용하면 되는 것입니다. 예를 들면 어떤 기능을 구현하는 코드는 완성이 되었지만 해당 코드에 보안 관련 기능은 아직 구현이 안되어다고 한다면 보안 관련 기능은 Stub 개체로 만들어서 테스트 코드를 작성하면 되는 것입니다.

기본편에서 살펴볼 마지막은 Event와 관련된 코드입니다.
[TestMethod]

public void Event_Registration()

{

    var view = MockRepository.GenerateMock<Form>();

 

    var presenter = new Presenter(view);

 

    view.Raise(t => t.Load += nullthisEventArgs.Empty);

 

    Assert.IsTrue(presenter.OnLoadCalled);

}

 

public class Presenter

{

    public bool OnLoadCalled { getset; }

 

    private Form loginForm;

 

    public Presenter(Form loginForm)

    {

        this.loginForm = loginForm;

        this.loginForm.Load += new EventHandler(loginForm_Load);

    }

 

    void loginForm_Load(object sender, EventArgs e)

    {

        OnLoadCalled = true;

    }

}

=> 위의 코드에서는 Mock 개체를 인터페이스가 아닌 Form클래스를 대상으로 만들었습니다. Raise()메서드가 해당 코드의 핵심 코드이며 Load이벤트가 발생 여부를 확인의 대상이 되는 클래스는 Presenter 클래스입니다. 이전과 마찬가지고 실질적으로 new키워드를 사용하여 인스턴스화 된 클래스가 검증 대상 클래스가 되며 이러한 이유는 Mock 개체는 일반적으로 인터페이스를 개체화 하기 때문입니다. 즉, 실질적인 생성된 검증 대상 클래스가 있어야 로직(여기서는 Load이벤트)가 실질적으로 발생했는지를 알 수 있기 때문입니다.

본 글에서는 Rhino Mock를 사용하는 기본적인 방법을 살펴보고 해당 방법을 통하여 Mocking Framework가 필요한 이유와 실질적으로 어떠한 상황에서 사용하는지를 간단히 살펴보았습니다.(물론 저의 생각.. ㅋㅋ)

다음 편을 쓸지는 장담할 수 없지만 DB 대신의 저장소의 역할을 하는 예제와 UI와 관련된 테스트 코드 작성 등등 좀 더 실질적으로 사용할 수 방법을 공유하도록 하겠습니다.

참고 사이트
http://ayende.com/wiki/Rhino+Mocks+3.5.ashx
http://builds.hibernatingrhinos.com/builds/Rhino-Mocks
저작자 표시 비영리 변경 금지
Posted by resisa