2012-04-02 77 views
0

背景:起订量多接口

我已经剥离了一个简单的代理事情在线上和部分发现我需要的实例部分基于我的WCF客户端。

用于创建客户端代理作为其公知的用法是:

WcfClientProxy<IServicecontract> clientProxy = 
           new WcfClientProxy<IServiceContract>(); 

WcfClientProxy有一个称为执行这需要方法:Expression<Func<TChannel, TResult>>Expression<Action<TChannel>>

我想要实现:

我想嘲笑这起订量使用,所以我可以测试通过客户服务合同的呼吁。

所以嘲笑这样的电话..

clientProxy.Execute(m=>m.DoSomeAction(5)); 

问题:

的问题是,模拟不起作用。我得到这个错误:

“抛出异常: System.NullReferenceException:对象引用未设置为对象的实例。”

我的测试服务合同是:

public interface ITestingServiceInterface : System.ServiceModel.IClientChannel 
{ 
    string Version(); 
    VersionDetail VersionDetail(); 
    IList<VersionDetail> VersionDetails(); 
    void DoSomeDelete(int itemId); 
} 

WCF客户端代理接口:

public interface IWcfClientProxy<TChannel> where TChannel : ICommunicationObject 
{ 
    bool ThrowOnException { get; set; } 
    TResult Execute<TResult>(Expression<Func<TChannel, TResult>> operation); 
    void Execute(Expression<Action<TChannel>> expression); 
} 

我试图测试,并与设置模拟..

private List<ProdItem> items; 
private Mock<IWcfClientProxy<ITestingServiceInterface>> mockClientProxy; 

[TestInitialize] 
public void SettingUp() 
{ 
    mockClientProxy = new Mock<IWcfClientProxy<ITestingServiceInterface>>(); 

    items = new List<ProdItem>(); 
    for(int i =0; i<10; i++){ 
     items.Add(new ProdItem { ProdItemId = i, LocalStock = i }); 
    } 
} 

[TestMethod] 
public void SimpleTest() 
{ 
    mockClientProxy.Setup(m => m.Execute(x => x.DoSomeDelete(It.IsAny<int>()))).Callback(RemoveItem); 

    var client = mockClientProxy.Object; 

    client.Execute(x => x.DoSomeDelete(4)); 

    Assert.AreEqual(9, items.Count); 
} 

public void RemoveItem() 
{ 
    items.RemoveAt(items.Count - 1); 
} 

此错误测试实际上是断言是错误的,似乎回调从未被击中。

我确信我刚刚做了一些愚蠢的事情。

更新: 显示的,我想怎样能够测试上述工作的例子..

[TestMethod] 
public void SimpleTest() 
{ 
    mockClientProxy.Setup(m => m.Execute(x => x.DoSomeDelete(It.IsAny<int>()))).Callback(RemoveItem); 

    var client = mockClientProxy.Object; 

    var stockHelper = new StockHelper(client); 

    stockHelper.DeleteItem(5); 

    Assert.AreEqual(9, items.Count); 
} 

在上面,我是测试StockHelper类需要在客户端代理它的构造函数通过它来调用WCF。

要测试StockHelper(或什么),我需要能够模拟客户端及其服务调用。上面的(第一)例子恶魔 - 直截了当地试图做到这一点。

我希望这是有道理的,请参阅我的最终目标不是测试模拟..这正是我必须尝试调试我的问题。

回答

2

正如我从你的代码可以看出,你正在测试模拟。我没有看到你正在测试的任何真实物体。 Mock用于存根被测试对象的依赖关系。所以,如果某个类Foo使用IWcfClientProxy那么你提供这个代理的模拟到Foo类。并验证在Foo.Bar()执行方法DoSomeDelete的依赖被调用。这就是嘲笑的目的。

[TestClass] 
public class FooTests 
{ 
    private Foo _foo; 
    private Mock<IWcfClientProxy<ITestingServiceInterface>> _clientProxy; 

    [TestInitialize] 
    public void SettingUp() 
    { 
     _clientProxy = new Mock<IWcfClientProxy<ITestingServiceInterface>>(); 
     _foo = new Foo(_clientProxy.Object); 
    } 

    [TestMethod] 
    public void SimpleTest() 
    { 
     // Act on object being tested 
     _foo.Bar(5); 

     // verify it executed correct method on dependency 
     _clientProxy.Verify(cp => cp.Execute(x => x.DoSomeDelete(5))); 
    } 
} 

测试Foo你不应该怎么在意_clientProxy在执行时记住。

+0

客户端代理一般会被传递到的东西,说一个辅助类。那么测试就是测试助手类而不是代理,但是因为我目前还没有证明这个代理是一个例子。如果我没有传递参数给服务方法,它按预期工作。 – 2012-04-02 10:14:54

+0

我已经更新了这个问题,(刚才看到您的更新后的答案)我是否需要使用验证而不是设置退货和回叫?那会是我的问题吗? – 2012-04-02 10:24:42

+0

代理具有方法'执行'。所以你需要验证这个方法是用正确的参数调用的。如果需要,您可以为模拟方法提供一些假返回值。 (对不起午餐时间,将在一小时内):) – 2012-04-02 10:27:35

0

有你的模拟设置事情很奇怪。我认为您设置的匹配参数仅限于第一层函数调用。您可能需要做一些事情,如:

mockClientProxy.Setup(m => m.Execute(It.IsAny<Expression<Action<TChannel>>>())).Callback(RemoveItem); 

起订量的工作原理是实现其参数的接口上的方法,在这种情况下,它的IWcfClientProxy<ITestingServiceInterface>接口方法。因此,当您将方法调用设置为执行时,您需要为参数设置匹配参数以执行。你在代码中做了什么就是为该特定的委托函数设置一个匹配项,该函数永远不会匹配任何内容,因为你不存储它并稍后调用Execute。