2014-05-01 13 views
24

Tôi đang thiết lập một số thử nghiệm đơn vị và sử dụng Rhino Mocks để điền đối tượng đang được thử nghiệm. Một trong những điều được chế nhạo là một Task<HttpResponseMessage>, vì logic đang được thử nghiệm bao gồm một cuộc gọi đến một số HttpClient để nhận phản hồi không đồng bộ.Làm thế nào để giả lập một tác vụ <> Kết quả?

Vì vậy, tôi đã bắt đầu thành lập mocks như thế này:

var httpClient = MockRepository.GenerateMock<HttpClient>(); 
var taskFunc = MockRepository.GenerateMock<Func<HttpResponseMessage>>(); 
var responseTask = MockRepository.GenerateMock<Task<HttpResponseMessage>>(taskFunc); 
var response = MockRepository.GenerateMock<HttpResponseMessage>(); 

httpClient.Stub(c => c.PostAsJsonAsync<IEnumerable<LogMessage>>(Arg<string>.Is.Anything, Arg<IEnumerable<LogMessage>>.Is.Anything)).Return(responseTask); 
responseTask.Stub(t => t.Result).Return(response); 
response.Stub(r => r.IsSuccessStatusCode).Return(true); 

(Các "hành động" bước của thử nghiệm sẽ được để nhanh chóng các đối tượng đang được thử nghiệm, nuôi nó httpClient, và chạy một phương pháp . vào nó các "khẳng định" sẽ xác minh qua mocks đó dự kiến ​​các cuộc gọi phương pháp đã được thực hiện trên chúng)

Bước qua chuyện này trong một trình gỡ lỗi, có một vô thời hạn treo trên dòng này:.

responseTask.Stub(t => t.Result).Return(response); 

Tôi không có nhiều kinh nghiệm với Rhino Mocks hoặc với C# async, vì vậy tôi có thể nhìn thấy một cái gì đó hiển nhiên. Tất nhiên, mục tiêu là mọi cuộc gọi đến bất động sản .Result sẽ trả lại mô hình response. Nhưng có vẻ như chính nỗ lực của tôi có lẽ đang gọi .Result mà tôi mong chờ đợi vô thời hạn vì nó chỉ là một mô hình, có lẽ?

Cách đúng để sắp xếp điều này là gì? Về cơ bản, tôi cần phải cung cấp đối tượng của tôi với một mô hình HttpClient giả định và khẳng định rằng một phương pháp đã được gọi trên đó với một đối số cụ thể.

+1

Tôi đã làm rất nhiều việc nhạo báng xung quanh Công việc khoảng một năm trước đây bằng cách sử dụng MOQ. Trừ khi tôi sai, bạn chỉ cần thay thế taskFunc mà bạn đang chuyển vào responseTask giả lập của bạn. Sau đó, có chức năng giả lập đó ngay lập tức trả về một phản ứng. – Keith

+0

@Keith: Thú vị. Vì vậy, chỉ cần tạo một 'Func ' thực thay vì một mô hình, mà chỉ trả về? Tôi chỉ cố gắng như vậy: 'Func taskFunc = delegate() {return response; }; 'và chuyển giao' taskFunc' đó cho mô phỏng 'responseTask', nhưng hành vi tương tự cũng được quan sát. – David

+1

Tôi không nghĩ rằng bạn cần một nhiệm vụ Mock thực tế. Những gì bạn cần để Mock là chức năng được chuyển vào Task, vì vậy nó sẽ chỉ trả về "x". – Keith

Trả lời

37

Điều đơn giản nhất chỉ là để trở về một nhiệm vụ hoàn thành với kết quả mong đợi:

var responseTask = Task.FromResult(response); 

Tôi tưởng tượng vì lý do này bị treo là nhiệm vụ chế giễu là không bao giờ bắt đầu và do đó func cụ thể được không chạy. Bạn có thể bắt đầu nó trong thử nghiệm của mình:

var responseTask = MockRepository.GenerateMock<Task<HttpResponseMessage>>(taskFunc); 
responseTask.Start(); 

Tuy nhiên không có lý do gì để tạo các tác vụ vì bạn có thể dễ dàng tạo công việc đã hoàn thành/thất bại/hủy.

+0

Có vẻ như đang thực hiện thủ thuật. Với điều này, tôi cũng cần phải loại bỏ sau hai lệnh gọi 'Stub()'. ('.Result' được xử lý bởi câu trả lời của bạn,' .IsSuccessStatusCode' đã ném một lỗi khi cố gắng để stub nó nhưng dường như mặc định để 'true' trong giả anyway.) Cảm ơn! – David

+0

Cảm ơn, điều này đã giúp tôi! – Aaron

Các vấn đề liên quan