2013-03-21 6 views
3

아래와 같이 코드를 고려하십시오. GetBrands를 호출하면 속성 브랜드에 적절한 데이터가 할당됩니다.비동기 void 메서드를 테스트하는 방법

public class BrandsViewModel : ViewModelBase 
{ 
    private IEnumerable<Brand> _brands; 
    public IEnumerable<Brand> Brands 
    { 
     get { return _brands; } 
     set { SetProperty(ref _brands, value); } 
    } 

    public async void GetBrands() 
    { 
     // ...... 

     Brands = await _dataHelper.GetFavoriteBrands(); 

     // ...... 
    } 
} 

그러나 아래와 같이 테스트하면 테스트가 실패합니다. GetBrands 메서드 내에서 비동기 호출을 기다리는 방법은 무엇입니까?

[TestMethod] 
public void AllBrandsTest() 
{ 
    BrandsViewModel viewModel = new BrandsViewModel(); 
    viewModel.GetBrands(); 
    Assert.IsTrue(viewModel.Brands.Any()); 
} 
+3

을 읽기 /하십시오이를 참조하십시오 http://blogs.msdn.com/b/ lucian/archive/2013/02/18/talk-the-new-async-design-patterns.aspx 기본적으로 다음과 같이 말합니다 : 이벤트 핸들러를 제외하고는'async void '를 사용하지 마십시오. –

+0

@DanielHilgarth, 감사합니다. 필자는 코드를 리팩토링했으며 매력처럼 작동합니다. – Shinbo

답변

8

간단한 대답은 다음과 같습니다. async void하지 마십시오. 실제로 을 만들지 마십시오. 절대적으로 이벤트 처리기로 작동해야하는 경우가 아니면 async void을 만듭니다. async void의 패배는 정확하게입니다. 여기에서 원하는 테스트 (실제 코드에 해당하는 것)가 있습니다.

대신 async Task 메쏘드로 만드십시오. 이제 완료 (시간 초과 포함)/연속 추가 및 성공 또는 예외로 종료했는지 여부를 확인할 수 있습니다.

이 하나의 단어 변화하는 것입니다

public async Task GetBrands() 
{ 
    // ...... 

    Brands = await _dataHelper.GetFavoriteBrands(); 

    // ...... 
} 

다음 테스트 :

[TestMethod] 
public async Task AllBrandsTest() 
{ 
    BrandsViewModel viewModel = new BrandsViewModel(); 
    var task = viewModel.GetBrands(); 
    Assert.IsTrue(task.Wait(YOUR_TIMEOUT), "failed to load in time"); 
    Assert.IsTrue(viewModel.Brands.Any(), "no brands"); 
} 
+0

'await'을 사용하지 않으면 왜 테스트를'async'로 했습니까? – svick

+0

@svick 그것은 OP에 대한 질문이며, 누가 그곳에서 '기다리고 있지 않습니다.' –

+0

@svick 제 잘못입니다. 테스트 코드를 수정했습니다. 메소드에서 기다리지 않으면 비동기를 유지할 필요가 없습니다. – Shinbo

1

모델 (DTO) 자체가 채워집니다 (데이터 액세스). 이것은 하나의 클래스가하기에는 너무 많은 것입니다. 대개 자신에게 물을 때 "어떻게이 지구를 테스트 할 수 있습니까?", 리팩토링 할 시간입니다. 별도의 데이터 액세스 클래스를 만듭니다.

BrandsViewModel viewModel = new BrandsViewModel(); 
var brandAccess = new BrandsDataAccess(); 
viewModel.Brands = await brandAccess.GetAllBrands(); 
Assert.IsTrue(viewModel.Brands.Any()); 

이제 BrandsDataAccess.GetAllBrands()을 테스트 할 수 있습니다.

+0

'async'는 어디로 갔습니까? 내 말은 : 원래의 코드는'async'이고, 당신의 코드는 아닙니다. 그래서 나는 그것이 좋은 대체물이라고 생각하지 않습니다. – svick

+0

@svick 그것은 구현이 아니라 중요하다는 원칙입니다. 편집을 참조하십시오. – CodeCaster

+0

@CodeCaster 더 자세히 설명해 주시겠습니까? Single Responsibility Principle의 관점에서 볼 때, 동일한 클래스 내의 자체 속성을 수용 할 수 있다고 생각합니다. 그렇지 않니? – Shinbo

관련 문제