Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 多接口_C#_Asp.net_Mocking_Moq - Fatal编程技术网

C# 多接口

C# 多接口,c#,asp.net,mocking,moq,C#,Asp.net,Mocking,Moq,背景: 我为我的Wcf客户端设计了一个简单的代理,部分基于在线找到的示例,部分基于我的需求 创建客户端代理的已知用法是: WcfClientProxy<IServicecontract> clientProxy = new WcfClientProxy<IServiceContract>(); 问题: 问题是模拟不起作用。我得到这个错误: “引发异常: System.NullReferenceExcep

背景:

我为我的Wcf客户端设计了一个简单的代理,部分基于在线找到的示例,部分基于我的需求

创建客户端代理的已知用法是:

WcfClientProxy<IServicecontract> clientProxy = 
                                 new WcfClientProxy<IServiceContract>();
问题:

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

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

我的测试服务合同是:

public interface ITestingServiceInterface : System.ServiceModel.IClientChannel
{
    string Version();
    VersionDetail VersionDetail();
    IList<VersionDetail> VersionDetails();
    void DoSomeDelete(int itemId);
}
公共接口ITestingServiceInterface:System.ServiceModel.IClientChannel
{
字符串版本();
VersionDetail VersionDetail();
IList 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);
}
公共接口IWCClientProxy,其中TChannel:ICommunicationObject
{
bool ThrowOnException{get;set;}
TResult Execute(表达式操作);
无效执行(表达式);
}
我尝试使用安装程序进行测试和模拟

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);
}
私有列表项;
私有mockClientProxy;
[测试初始化]
公共无效设置()
{
mockClientProxy=newmock();
项目=新列表();
for(inti=0;im.Execute(x=>x.DoSomeDelete(It.IsAny()))).Callback(removitem);
var client=mockClientProxy.Object;
client.Execute(x=>x.DoSomeDelete(4));
Assert.AreEqual(9项,计数);
}
公共无效删除项()
{
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);
}
[TestMethod]
public-void-SimpleTest()
{
mockClientProxy.Setup(m=>m.Execute(x=>x.DoSomeDelete(It.IsAny())).Callback(removitem);
var client=mockClientProxy.Object;
var stockHelper=新的stockHelper(客户端);
stockHelper.DeleteItem(5);
Assert.AreEqual(9项,计数);
}
在上面,我正在测试StockHelper类,该类在其构造函数中使用客户端代理,通过该代理调用WCF

为了测试StockHelper(或者其他什么),我需要能够模拟客户端及其服务调用。上面(第一个)的例子恶魔直我有一个问题,试图这样做


我希望这是有道理的,请注意我的最终目标不是测试模拟。。这正是我试图调试我的问题的地方

从您的代码中可以看出,您正在测试mock。我没有看到任何你正在测试的真实物体。模拟用于存根被测试对象的依赖关系。因此,如果某个类
Foo
使用
iwcclientproxy
,那么您可以向类
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)));
    }
}
[TestClass]
公营足球场
{
私人富富;;
私有模拟客户端代理;
[测试初始化]
公共无效设置()
{
_clientProxy=newmock();
_foo=新的foo(_clientProxy.Object);
}
[测试方法]
public-void-SimpleTest()
{
//作用于被测对象
_富吧(5);;
//验证它对依赖项执行了正确的方法
_验证(cp=>cp.Execute(x=>x.DoSomeDelete(5));
}
}

请记住,在测试
Foo
时,您不应该关心
\u clientProxy
是如何实现的。

模拟设置中出现了一些奇怪的情况。我认为您设置的匹配参数仅限于函数调用的第一层。您可能需要执行以下操作:

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

Moq的工作原理是在其参数的接口上实现方法,在本例中是
iwcflientproxy
的接口方法。因此,在设置要执行的方法调用时,需要为要执行的参数设置匹配参数。您在代码中所做的是为特定的委托函数设置一个匹配项,该函数实际上永远不会匹配任何东西,因为您不存储它并稍后使用它调用Execute。

客户端代理通常会被传递给某个对象,例如帮助器类。然后测试将是测试helper类,而不是代理,但是因为我目前无法测试代理,所以我没有将其作为示例。如果我没有向服务方法传递任何参数,它将按预期工作。我已经更新了问题(刚刚看到您更新的答案),我是否需要使用验证而不是设置返回和回调?这是我的问题吗?代理具有方法
Execute
。因此,您需要验证是否使用正确的参数调用了此方法。如果需要,您可以为模拟方法提供一些假返回值。(抱歉,午餐时间,一小时后回来):)尝试过了,它抱怨从未调用该方法。顺便说一句,如果您想检查表达式参数的精确匹配,我认为使用moq是不可能的:
mockClientProxy.Setup(m => m.Execute(It.IsAny<Expression<Action<TChannel>>>())).Callback(RemoveItem);