2011-04-19 2 views
2

는 여기에 지금까지 내 테스트에있는 내용은 다음과 같습니다단위 테스트에서 문자열 응답을 조롱하려면 어떻게해야합니까?

[TestFixture] 
public class IndividualMovieTests 
{ 
    [Test] 
    public void WebClient_Should_Download_From_Correct_Endpoint() 
    { 
     const string correctEndpoint = "http://api.rottentomatoes.com/api/public/v1.0/movies/{movie-id}.json?apikey={your-api-key}"; 
     ApiEndpoints.Endpoints["IndividualMovie"].ShouldEqual(correctEndpoint); 
    } 

    [Test] 
    public void Movie_Information_Is_Loaded_Correctly() 
    { 
     Tomato tomato = new Tomato("t4qpkcsek5h6vgbsy8k4etxdd"); 
     var movie = tomato.FindMovieById(9818); 
     movie.Title.ShouldEqual("Gone With The Wind"); 
    } 
} 

내 FIndMovieById 방법은 온라인 상태와 JSON 결과를 가져, 그게 일종의 원칙 뒤에 단위 테스트를 나누기 의미한다. 이 문자열 응답을 조롱해야한다는 느낌이 들지만 실제로 어떻게 접근해야하는지 모르겠습니다.

은 어떻게이 단위 테스트에 접근합니까?

+2

조롱 프레임 워크를 사용 해본 적이 있습니까? 외부 API 호출을하는 메소드에 대해 단위 테스트를 많이 수행하려는 경우에는 매우 유용 할 수 있습니다. –

답변

3

두 번째 [Test]에서는 특정 입력 값이 항상 "바람과 함께 사라지다"라는 테스트를 실제로하지 않는 한 FindMovieById 메서드의 특정 반환 값에 초점을 두지 않을 것을 제안합니다. 테스트는 특정 입력 번호로 인해 특정 출력이 나오는 매우 구체적인 테스트 케이스 인 것 같습니다. 이는 실제 데이터베이스를 실행 중일 때 변경 될 수도 있고 변경되지 않을 수도있는 것입니다. 또한 실제 웹 서비스에 대해 테스트하지 않기 때문에 이러한 종류의 유효성 검사를 수행하는 것은 기본적으로 셀프 서비스입니다. 실제로 테스트하지는 않습니다. 대신 Tomato 클래스가 인수의 유효성 검사 (있는 경우)를 처리하는 방법을 테스트하고 Tomato 클래스가 실제로 반환 값을 얻기 위해 서비스를 호출하는지 테스트하는 데 중점을 둡니다. 특정 입력 및 출력을 테스트하는 대신 클래스의 동작을 테스트하십시오. 따라서 누군가가 나중에이를 변경하면 테스트가 중단되어 작동 기능이 손상되었을 수 있음을 경고해야합니다.

예를 들어 입력 유효성 검사가있는 경우 잘못된 입력이 감지되면 Tomato 클래스가 예외를 throw하는지 테스트 할 수 있습니다.

Tomato 클래스에 결과 요청 및 검색을위한 일종의 웹 클라이언트 기능이 있다고 가정하면 실제 웹 코드의 스텁 구현이나 조롱 된 구현을 플러그인하여 Tomato가 실제로 적절한 웹을 호출하도록 할 수 있습니다 클라이언트 코드는 응답을 요청하고 처리합니다.

2

먼저 코드를 테스트하기 위해 모의하지 않아도됩니다. 예를 들어, JSON을 Movie 객체로 역 직렬화 할 수 있는지 테스트하는 중이라면 Movie 클래스에서 공용 또는 내부 ParseJSON 명령을 테스트하여이를 수행 할 수 있습니다.

그러나 조롱에 대해 묻기 때문에 모의를 사용하여이 테스트를 작성할 수있는 방법 중 하나를 간략히 살펴 보겠습니다. 작성된대로 Movie_Information_Is_Loaded_Correctly()은 통합 테스트와 유사합니다. 이것을 단위 테스트로 바꾸려면 은 웹 요청을 Tomato 클래스가 조롱하도록 만들 수 있습니다. 한 가지 방법은 ITomatoWebRequester 인터페이스를 만들고이를 생성자의 Tomato 클래스에 대한 매개 변수로 전달하는 것입니다. 그런 다음 ITomatoWebRequester을 조롱하여 예상하는 웹 응답을 반환하면 Tomato 클래스가 해당 응답을 올바르게 구문 분석하는지 테스트 할 수 있습니다.

코드는 다음과 같은 것을 볼 수 있었다 :

public class Tomato 
{ 
    private readonly ITomatoWebRequester _webRequester; 
    public Tomato(string uniqueID, ITomatoWebRequester webRequester) 
    { 
     _webRequester = webRequester; 
    } 

    public Movie FindMovieById(int movieID) 
    { 
     var responseJSON = _webRequester.GetMovieJSONByID(movieID); 
     //The next line is what we want to unit test 
     return Movie.Parse(responseJSON); 
    } 
} 

public interface ITomatoWebRequester 
{ 
    string GetMovieJSONByID(int movieID); 
} 

이 테스트하려면, 당신은 당신이 기대하는 결과를 반환하는 ITomatoWebRequester을 만들 MOQ 같은 조롱 프레임 워크를 사용할 수 있습니다. MOQ에 다음과 같은 코드가 작동해야 수행합니다

[Test] 
public void Movie_Information_Is_Loaded_Correctly() 
{ 
    var mockWebRequester = new Moq.Mock<ITomatoWebRequester>(); 
    var myJson = "enter json response you want to use to test with here"; 
    mockWebRequester.Setup(a => a.GetMovieJSONByID(It.IsAny<int>()) 
     .Returns(myJson); 

    Tomato tomato = new Tomato("t4qpkcsek5h6vgbsy8k4etxdd", 
     mockWebRequester.Object); 
    var movie = tomato.FindMovieById(9818); 
    movie.Title.ShouldEqual("Gone With The Wind"); 
} 

이 경우 모의에 대한 좋은 점은 걱정하지 않아도됩니다 실제 ITomatoWebRequester는 JSON을 반환을 통해 이동이에 대한 모든 농구 돌아 오면, 테스트에서 정확히 원하는 것을 반환하는 조롱을 만들 수 있습니다. 바라건대이 대답은 조롱하는 데 알맞은 인트로 역할을하기를 바랍니다. 분명히 프로세스를 작동하는 방법에 대한 더 나은 느낌을 얻기 위해 조롱 프레임 워크를 읽는 것이 좋습니다.

1

Rhino.Mocks 라이브러리를 사용하고 필요할 때마다 기대를 호출하십시오. 다음은 무비 객체 조롱 샘플입니다.

using System; 
using NUnit.Framework; 
using Rhino.Mocks; 
namespace ConsoleApplication1 
{ 
    public class Tomato 
    { 
     public Tomato(string t4qpkcsek5h6vgbsy8k4etxdd) 
     { 
      // 
     } 

     public virtual Movie FindMovieById(int i) 
     { 
      return null; 
     } 
    } 

    public class Movie 
    { 
     public string Title; 

     public Movie() 
     { 

     } 

     public void FindMovieById(int i) 
     { 
      throw new NotImplementedException(); 
     } 
    } 

    [TestFixture] 
    public class IndividualMovieTests 
    { 
     [Test] 
     public void Movie_Information_Is_Loaded_Correctly() 
     { 

      //Create Mock. 
      Tomato tomato = MockRepository.GenerateStub<Tomato>("t4qpkcsek5h6vgbsy8k4etxdd"); 

      //Put expectations. 
      tomato.Expect(t=>t.FindMovieById(0)).IgnoreArguments().Return(new Movie(){Title ="Gone With The Wind"}); 

      //Test logic. 
      Movie movie = tomato.FindMovieById(9818); 

      //Do Assertions. 
      Assert.AreEqual("Gone With The Wind", movie.Title); 

      //Verify expectations. 
      tomato.VerifyAllExpectations(); 
     } 
    } 
} 
관련 문제