Tôi có một ứng dụng Silverlight điển hình với dịch vụ WCF và tôi đang sử dụng slsvcutil.exe để tạo proxy máy khách chuẩn để giao tiếp với dịch vụ web. Tôi đang cố gắng để viết bài kiểm tra đơn vị và tôi đang cố gắng sử dụng khung kiểm tra đơn vị Silverlight và Moq để giả mạo proxy và loại bỏ sự phụ thuộc dịch vụ để thử nghiệm.Gọi các cuộc gọi không đồng bộ trong Silverlight WCF Proxy bằng cách sử dụng Moq
Tôi rất mới đối với Moq và gặp rất nhiều sự cố khi tự động tăng các sự kiện hoàn thành trên proxy giả tự động khi cuộc gọi dịch vụ được thực hiện để mô phỏng các cuộc gọi không đồng bộ.
Để làm cho proxy "mockable" Tôi đã tạo ra giao diện đơn giản của riêng mình cho các cuộc gọi proxy tạo ra và các sự kiện hoàn thành của họ:
public interface IServiceProxy
{
void TestAsync(TestRequest request);
void TestAsync(TestRequest request, object userState);
event EventHandler<TestCompletedEventArgs> TestCompleted;
}
Tôi cũng subclassed đối tượng proxy được tạo ra để thực hiện giao diện:
public class MyServiceProxy : GeneratedServiceClient, IServiceProxy, ICommunicationObject
{
// ... overloaded proxy constructors
}
Sau khi xem xét các tài liệu Moq, đây là cách tôi đang cố gắng để thiết lập các mô hình để dự đoán() gọi TestAsync và ngay lập tức nâng cao sự kiện TestCompleted với kết quả trong EventArgs:
[TestMethod]
public void Test_Returns_Expected()
{
var mockProxy = new Mock<IServiceProxy>();
var result = new TestResponse() { Value = true };
this.mockProxy.Setup(
p => p.TestAsync(It.IsAny<TestRequest>()))
.Raises(p => p.TestCompleted += null, new TestCompletedEventArgs(new object[] { result }, null, false, null));
// rest of the test to actually use the mock and assert things
}
Mọi thứ đều tốt, nhưng khi tôi cố gắng chạy bất kỳ loại thử nghiệm nào bằng cách sử dụng giả lập và đặt điểm ngắt, sự kiện TestCompleted sẽ không bao giờ được nâng lên khi tôi gọi TestAsync().
Có bất kỳ điều gì rõ ràng rằng tôi bị thiếu hoặc có bất kỳ ý tưởng nào tốt hơn về chế nhạo các loại proxy dịch vụ không đồng bộ này trong Silverlight không?
Cảm ơn!
EDIT:
Để được rõ ràng hơn những gì tôi đang thực sự cố gắng để thử nghiệm là một lớp helper tôi đã thực hiện trong đó có một thể hiện của IServiceProxy
và cung cấp một giao diện dịch vụ làm sạch cho ViewModel của tôi để sử dụng bằng cách chấp nhận Action<TResponse, Exception>
callback tham số thay vì xử lý các sự kiện gọi lại trong ViewModel của tôi. Tôi hiểu làm thế nào tôi có thể thử này cũng như để trực tiếp kiểm tra ViewModel của tôi, nhưng tôi figured nó sẽ là tốt đẹp để kiểm tra lớp helper của chính nó đầu tiên.
Dưới đây là một ví dụ về những gì tôi đang nói về:
public class HelperClient : IServiceHelper
{
private IServiceProxy proxy;
public HelperClient(IServiceProxy proxy)
{
this.proxy = proxy;
// register to handle all async callback events
this.proxy.TestCompleted += new EventHandler<TestCompletedEventArgs>(TestCompleted);
}
public void Test(TestRequest request, Action<TestResponse, Exception> response)
{
this.proxy.TestAsync(request, response);
}
private void TestCompleted(object sender, TestCompletedEventArgs e)
{
var response = e.UserState as Action<TestResponse, Exception>;
if (response != null)
{
var ex = GetServiceException(e);
if (ex == null)
{
response(e.Result, null);
}
else
{
response(null, ex);
}
}
}
}
Vì vậy, trong thử nghiệm của tôi những gì tôi đang thực sự làm được chế giễu ISerivceProxy và đi qua nó và chỉ cố gắng để thử nghiệm một dịch vụ gọi để đảm bảo bao bọc nó gọi hành động một cách chính xác:
[TestMethod]
[Asynchronous]
public void Test_Returns_Expected()
{
var mockProxy = new Mock<IServiceProxy>();
var helper = new HelperClient(mockProxy.Object);
bool expectedResult = true;
var result = new TestResponse() { Value = expectedResult };
this.mockProxy.Setup(
p => p.TestAsync(It.IsAny<TestRequest>()))
.Raises(p => p.TestCompleted += null, new TestCompletedEventArgs(new object[] { result }, null, false, null));
helper.Test(new TestRequest(), (response, ex) =>
{
Assert.AreEqual(expectedResult, response.Value);
EnqueueTestComplete();
});
}
vấn đề là đối tượng proxy chế giễu là không bao giờ nâng cao sự kiện TestCompleted nên hành động phản ứng của tôi là không bao giờ bị viện dẫn để hoàn tất việc thử nghiệm (mặc dù các thử nghiệm xuất hiện để hoàn thành công Khẳng định là ne ver thực sự chạy). Xin lỗi vì bài đăng dài như vậy, chỉ cố gắng hiển thị cho bạn nhiều mã nhất có thể.
EDIT 2
Added [Asynchronous]
và gọi đến EnqueueTestComplete()
mà tôi nhận ra rằng tôi có thể cần phải thực hiện các thử nghiệm chờ đợi cho sự kiện này được nâng lên.Điều này đã không thực sự giúp đỡ, sự kiện này vẫn chưa bao giờ được nêu ra để thử nghiệm chỉ bị treo và không bao giờ hoàn thành.
EDIT 3
câu trả lời Aliostad là đúng khi cho rằng chữ ký thiết lập kỳ vọng của tôi không khớp với chữ ký thực tế thử nghiệm() cho phép tôi vượt qua trong một hành động phản ứng như param thứ hai. Sai lầm ngu ngốc, nhưng đó là những gì đã ngăn cản Moq từ việc nâng cao sự kiện đã hoàn thành. Tôi cũng đã quên chuyển Action thành đối tượng userState trong TestCompletedEventArgs để nó thực sự được gọi khi sự kiện Completed được nâng lên. Ngoài ra, [Asynchronous]
và EnqueueTestCompleted
dường như không cần thiết trong trường hợp này.
đây được cập nhật mã kiểm tra cho bất cứ ai quan tâm:
[TestMethod]
public void Test_Returns_Expected()
{
var mockProxy = new Mock<IServiceProxy>();
var helper = new HelperClient(mockProxy.Object);
bool expectedResult = true;
var result = new TestResponse() { Value = expectedResult };
Action<TestResponse, Exception> responseAction = (response, ex) =>
{
Assert.AreEqual(expectedResult, response.Value);
};
this.mockProxy.Setup(
p => p.TestAsync(It.IsAny<TestRequest>(), It.IsAny<Action<TestResponse, Exception>>()))
.Raises(p => p.TestCompleted += null, new TestCompletedEventArgs(new object[] { result }, null, false, responseAction));
helper.Test(new TestRequest(), responseAction);
}
Xin chào, tôi đã cập nhật câu trả lời của mình. Vấn đề của bạn là đặt kỳ vọng vào một phương thức có chữ ký khác với chữ ký bạn đang gọi trong lớp trợ giúp của bạn. – Aliostad