2010-08-13 2 views
0

(C#, Rhino Mocks, MbUnit).관찰 가능한 상태 변경이없는 메소드를 테스트하는 유닛

AccountManager라는 클래스에는 RegisterUser() 메서드가 있습니다. 이 메서드는 void를 반환하지만 오류가 발생할 경우 예외를 throw합니다. AccountManager는 AddUser() 메서드를 호출하는 IDataRepository를 호출하여 데이터베이스 삽입을 수행합니다.

Rhino Mock을 사용하여 IDataRepository를 조롱하고 저장소에서 발생하는 예외를 시뮬레이트하는 주어진 인수 집합에 대해 예외 및 예외가 발생했습니다.

[Test] 
    public void RegisterKnownUser() 
    { 
     MockRepository mocks = new MockRepository(); 
     IDataRepository dataRepository = mocks.StrictMock<IDataRepository>(); 

     using (mocks.Record()) 
     { 
      Expect.Call(() => dataRepository.AddUser("abc", "abc", "[email protected]", "a", "bc")).Throw(
       new InvalidOperationException()); 
     } 

     using (mocks.Playback()) 
     { 
      AccountManager manager = new AccountManager(dataRepository); 
      Assert.Throws(typeof (InvalidOperationException),() => manager.RegisterUser("abc", "abc", "[email protected]", "a", "bc")); 
     } 
    } 

이 테스트는 정상적으로 작동합니다.

제 질문은 RegisterUser에 제공된 args가 올 바르고 유효한지 여부에 관한 것입니다. 실제 IDataRepository는 아무 것도 반환하지 않으며 예외가 발생하지 않습니다. 따라서 짧은 AccountManager의 상태는 변경되지 않았습니다. 이 말은 AccountManager.RegisterUser를 테스트 할 필요가 없기 때문에 테스트 할 클래스와 메소드에서 직접 관찰 할 수있는 결과가 아닐 수 있습니다. 가짜의 상태에 대한 테스트는 나에게 약간의 냄새를 맡는다. 나는 IDataRepository.AddUser를 개별적으로 테스트하는 한, AccountManager.RegisterUser를 클래스에서 관찰 할 수없는 결과가 나오는지 테스트 할 필요가 없어야한다고 생각합니다.

미리 감사드립니다.

+0

Ribgy : 설명하려는 테스트 케이스에 대한 코드를 제공 할 수 있습니까? AccountManager가 dataRepository를 호출할까요? –

답변

2

AccountManager가 DataPrepository를 호출하는 경우 테스트 케이스는 여전히 무언가를 확인합니다. 녹음/재생은 여기에 전화가 걸리는 것을 확인합니다. 호출이 이루어지지 않으면 테스트 케이스가 실패합니다. 잘못된 인수로 두 번 만들면 실패합니다.

이것은 매우 기본적인 테스트 케이스 일 수 있지만 여전히 좋은 테스트 케이스이며 mock 객체에 상태를 둘 필요는 없습니다.

+0

감사합니다 (그리고 Main Ma도 마찬가지입니다). 나는 좋은 데이터를 위해 던져지지 않은 예외를 테스트하는 길을 갔다. –

0

유효한 인수를 사용하여 메서드를 테스트하여 이 예외을 throw하지 않도록 할 수 있습니다. 즉, 상태 변경을 관찰하거나 리턴 값을 사용할 수 없지만 (예외가 없으므로) 메소드가 예외없이 실행되었음을 알 수 있습니다. 이 방법은 값을 반환하거나 AccountManager 상태를 변경하지 않는 경우 그런데

그것은 (당신은 아마 당신의 코드에서 모든에 아무것도하지 않는 방법을 제거하는 것보다, 그렇지 않은 경우) 그렇지 않으면 뭔가를 변경 않는다 .
예를 들어, DataRepository에 영향을 줄 수 있습니다. 또는 데이터베이스에 레코드를 추가하십시오. 이 경우 최소한 데이터가 변경되었거나 레코드가 성공적으로 추가되었는지 테스트 할 수 있습니다. 또는 새로운 사용자가 등록되었다는 것을 나타내는 이벤트를 기록 할 수 있으므로 테스트에서 로그 이벤트가 있는지 확인할 수 있습니다.

나는 별도로 그때 AccountManager.RegisterUser가 아무것도 추가하지

경우 수업 시간에 관찰 아무것도 초래 입력에 대해 AccountManager.RegisterUser를 테스트 할 필요가 없습니다만큼 내가 IDataRepository.AddUser을 테스트로 생각 인수 실행을 제외하고 IDataRepository.AddUser 인 경우, IDataRepository.AddUser을 이미 테스트 한 경우 테스트하지 않아도됩니다. 인수를 확인하는 경우 AddUser을 호출하고을 실행하면 올바르게 작동하는지 확인하는 것이 좋습니다.

의 당신이 있다고 가정 해 봅시다 :

public void AddUser(string userName, string userMail, string passwordHash) 
{ 
    // [...] Add a user to the database. 
} 

public void RegisterUser(string userName, string userMail, string passwordHash) 
{ 
    if (string.IsNullOrEmpty(userName)) throw new ArgumentNullException(...); 
    if (string.IsNullOrEmpty(userMail)) throw new ArgumentNullException(...); 
    if (string.IsNullOrEmpty(passwordHash)) throw new ArgumentNullException(...); 
    if (!Checks.IsValidMail(userMail)) throw new ArgumentException(...); 

    this.AddUser(userName, userMail, passwordHash); 

    this.SaveToLog(LogEvent.UserRegistered, userName, this.IPAddress); 
} 

RegisterUser에서 잘못된 인수를 전달하고 예외를 예상하여 처음 네 줄을 테스트합니다. 이미 AddUser을 테스트 했으므로 다섯 번째 줄은 테스트하지 말아야합니다. 마지막으로 유효한 인수를 사용하여 RegisterUser을 호출하면 로그 항목이 작성되도록 6 행을 테스트해야합니다.