Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/296.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# 使用Moq模拟不安全的接口_C#_Unit Testing_Pointers_Moq_Unsafe - Fatal编程技术网

C# 使用Moq模拟不安全的接口

C# 使用Moq模拟不安全的接口,c#,unit-testing,pointers,moq,unsafe,C#,Unit Testing,Pointers,Moq,Unsafe,是否可以使用Moq模拟不安全的接口?例如,我有(MCVE): 是否可以在不使用类型参数的情况下设置模拟以避免此问题 (我知道显而易见的解决方案是不要使用不安全的接口,我想知道是否有一种解决方案可以使用不安全的接口。) 编辑/更新:可以使用存根类,但如果可以使用Moq,我希望避免这种情况,因为Moq提供的代码要少得多 public unsafe class MyUnsafeClass : IMyUnsafeInterface { public void DoWork(int* intPtr

是否可以使用Moq模拟不安全的接口?例如,我有(MCVE):

是否可以在不使用类型参数的情况下设置模拟以避免此问题

(我知道显而易见的解决方案是不要使用不安全的接口,我想知道是否有一种解决方案可以使用不安全的接口。)

编辑/更新:可以使用存根类,但如果可以使用Moq,我希望避免这种情况,因为Moq提供的代码要少得多

public unsafe class MyUnsafeClass : IMyUnsafeInterface
{
    public void DoWork(int* intPtr) {
        // Do something
    }
    public byte* MethodNotRelevantToThisTest1(byte* bytePtr) {
        throw new NotImplementedException();
    }
    public ComplexObject MethodNotRelevantToThisTest2() {
        throw new NotImplementedException();
    }
    ...
}

快速回答如果您的类型在方法签名中有指针类型,则不可能


您看到的错误是因为无法将指针用作类型参数。实际上,您可以在第4.4.1节(类型参数)中找到:

在不安全代码中,类型参数不能是指针类型

通过更改代码以期望使用特定指针,可以避免此特定错误:

Mock<IMyUnsafeInterface> mockDependency = new Mock<IMyUnsafeInterface>();

mockDependency.Setup(i => i.DoWork(any));

// use the mock
mockDependency.Object.DoWork(any);

mockDependency.Verify(p => p.DoWork(any));
这似乎是可行的,但它失败了,只有一个例外:

System.Security.VerificationException : Operation could destabilize the runtime. at lambda_method(Closure) at Moq.MatcherFactory.CreateMatcher(Expression expression, Boolean isParams) at Moq.MethodCall..ctor(Mock mock, Func`1 condition, Expression originalExpression, MethodInfo method, Expression[] arguments) at Moq.Mock.Verify(Mock mock, Expression`1 expression, Times times, String failMessage) at Moq.Mock`1.Verify(Expression`1 expression) 然后在你的测试中:

int* any = stackalloc int[4];
int* other = stackalloc int[4];
var stubMyUnsafeInterface = new StubMyUnsafeInterface(any);

stubMyUnsafeInterface.DoWork(any);   // passes
stubMyUnsafeInterface.DoWork(other); // fails

为了避免这种情况,您可以尝试使用包装类概念。您可以简单地包装原始类或接口。然后可以在包装类函数中使用原始函数。如下面的示例所示-

//Wrapper class
public class MyWrapperClass
{
     public YourReturnType MyFunction()
     {
         OriginalClass obj = new OriginalClass();

         //And inside this function call your original function
         return obj.OriginalFunction();
     }

}
包装器类包装原始类型,我们可以根据需要使用/模拟原始对象

如果您不知道包装类的概念,那么首先要理解它的概念


这似乎没有回答这个问题。问题是“我怎样才能用mock来解决这个问题?”@Chris Yep,我刚刚扩展了,我正在尝试提出替代方案。是的,我在点击submit时看到了。我的主要疑问是,是否有不使用泛型和lambda来设置Moq对象的不太常见的方法,但我对Moq还不太熟悉,所以不能这么说。这听起来是个不错的建议。我最初的帖子包含一个MCVE,但我的实际界面包含几个方法;一些带有
int*
参数,一些带有
byte*
,还有一些带有我不想模拟的方法。Moq的一个好处是,我只嘲笑相关的方法。理想情况下,我希望坚持使用Mock的方法。@Jonny理解,但我不认为Moq可以支持它,因为调用
Setup
/
Verify
归结为创建一个通用的
Matcher
,它不适用于指针类型。我不太确定这在这里是如何应用的。我的目标是通过使用Moq避免中断接口。我也没有
OriginalClass
——只有一个接口,所以我不能调用
OriginalFunction()
,因为没有实现。
unsafe class StubMyUnsafeInterface : IMyUnsafeInterface
{
    readonly int* expectedIntPtr;

    public StubMyUnsafeInterface(int* expectedIntPtr)
    {
        this.expectedIntPtr = expectedIntPtr;
    }

    public unsafe void DoWork(int* intPtr)
    {
        Assert.That(intPtr == expectedIntPtr);
    }
}
int* any = stackalloc int[4];
int* other = stackalloc int[4];
var stubMyUnsafeInterface = new StubMyUnsafeInterface(any);

stubMyUnsafeInterface.DoWork(any);   // passes
stubMyUnsafeInterface.DoWork(other); // fails
//Wrapper class
public class MyWrapperClass
{
     public YourReturnType MyFunction()
     {
         OriginalClass obj = new OriginalClass();

         //And inside this function call your original function
         return obj.OriginalFunction();
     }

}