C# 使用Moq模拟不安全的接口
是否可以使用Moq模拟不安全的接口?例如,我有(MCVE): 是否可以在不使用类型参数的情况下设置模拟以避免此问题 (我知道显而易见的解决方案是不要使用不安全的接口,我想知道是否有一种解决方案可以使用不安全的接口。) 编辑/更新:可以使用存根类,但如果可以使用Moq,我希望避免这种情况,因为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
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();
}
}