首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >c#如何测试接口引用

c#如何测试接口引用
EN

Stack Overflow用户
提问于 2012-12-11 08:29:00
回答 1查看 1.1K关注 0票数 2

我以前问过一个关于如何set value of interface in testing a method的问题。我已经成功地在我的项目中实现了Moq框架,并且测试运行良好。

这是我提供的示例代码:

代码语言:javascript
复制
public void PostEvent(
            eVtCompId inSenderComponentId, 
            eVtEvtId inEventId, 
            long inEventReference, 
            IF_SerializableData inEventData)
{
    if(mEventMap.ContainsKey(inEventId))
    {
        mEventMap[inEventId](inSenderComponentId, inEventReference, inEventData);
    }
}

这里我有4个参数:1:枚举,2:另一参数,3:长,4:接口。--然而,,我错了,因为第四个参数(接口)不应该是接口,而是接口的reference

所以应该是这样的:

代码语言:javascript
复制
public void PostEvent(
       eVtCompId inSenderComponentId, 
       eVtEvtId inEventId, 
       long inEventReference, 
       ref IF_SerializableData inEventData)

给我的Moq测试代码样本(就是这个).

代码语言:javascript
复制
var serializable = new Mock<IF_SerializableData>();
target.PostEvent(..., serializable.Object);

.行不通我尝试过ref serializable.Object,但是它仍然不能工作,因为我得到了一个错误,即ref参数期望一个变量的引用,而不是一个对象。

关于如何正确地测试这一点,有什么建议或例子吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-12-11 08:53:12

您需要将Object引用从serializable模拟复制到一个局部变量中,这样就可以将它作为ref传递。

代码语言:javascript
复制
IF_SerializableData localRef = serializable.Object;
target.PostEvent(..., ref localRef);

您不能传递ref Serializable.Object,因为它是一个属性--参见Is it possible to pass properties as "out" or "ref" parameters?,它提供了关于为什么会出现这种情况的极好的讨论,以及其他链接的来源。

我的解释

这最终是因为属性不是变量。读/写属性是一对getset访问器方法,它们提供类似变量的功能,但关键的是,当您对属性进行get时,您总是得到底层变量的副本--即使该变量具有引用类型。

所以:

代码语言:javascript
复制
public class MyClass {
  private object _property;
  public object Property {
    get { return _property; } //<-- _property reference copied on to stack & returned
                              //    here as a new variable.  Therefore a ref
                              //    on that is effectively meaningless.
                              //    for a ref to be possible you'd need a pointer 
                              //    to the _property variable (in C++ terms)
    set { _property = value; }
  }
}

在本例中--如果您可以将ref MyClass.Property传递给一个方法--它将毫无意义,因为它将传递对堆栈中一个瞬态变量的引用--即Property get accessor; it would not be passing the property by reference. So C# doesn't allow it, even though it could, because it would imply thatProperty`‘返回的引用的副本可以由该方法修改--而它根本不能。

因此,在您的情况下,我们需要从堆栈中捕获该值并将其复制到局部变量中。现在-注意,为了使ref方法设置的新值出现在Mock<T>上,您需要再次将它的Object属性设置为局部变量值(如果可以的话--我不使用Moq,但假设它是不可变的)。

对于C#是否应该以这种方式自动处理ref Property (请参阅前面提到的,所以我链接到),已经有了很多争论。在我看来,这类似于ref Derivedref Base不兼容-是的,有一种方法可以自动地为您处理这个问题,但是它应该吗?在我看来,没有。我会因此而受挫吗?是的,当然--但我经常发现它突出了真正应该修复的体系结构缺陷(例如,依赖返回值可能更好的refout参数)。

C#允许您通过引用传递属性的唯一方法是将get和set访问器传递到目标方法--这与ref完全不兼容(因为这只是一个内存位置)。

作为体验者,您必须编写这样的方法,如下所示:

代码语言:javascript
复制
 public static void MyUglyRefMethod(Func<object> refGet, Action<object> refSet)
 {
   var read = refGet();
   var newValue = new object();
   refSet(newValue);
 }

有了这个,我们现在可以在MyClass上提供类似于MyClass的语义

代码语言:javascript
复制
 MyClass a = new MyClass();
 MyUglyRefMethod(() => a.Property, (newValue) => a.Property = newValue);
 Assert.IsNotNull(a.Property);

但这简直太丑了。

创建一个获取ref MyClass的方法比较简单,然后它可以直接写入任何属性。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13816305

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档