2012-11-29 275 views
2

期间需要挖孔的BeginInvoke援助掉委托类型。在我的课,我已经声明了一个委托类型,我创建它的一个实例,然后调用的BeginInvoke关闭该实例:单元测试

public class ClassA 
{ 
    ... 
    public delegate bool MyDelegate(int x); 
    ... 
    public void MethodA() 
    { 
     ... 
     var myDelegate = new MyDelegate(Foo); 
     myDelegate.BeginInvoke(...); 
     ... 
    } 
    ... 
} 

在为MethodA编写单元测试,我不需要实际上曾经想要调用BeginInvoke。我想要做的就是使用Moles框架来完成BeginInvoke调用。通常,我会尝试

MMyDelegate.AllInstances.BeginInvoke... = (...) => { /* something here */ } 

但我一直无法得到痣产生任何MyDelegate类型。

根据http://msdn.microsoft.com/en-us/library/system.delegate.aspx,“公共语言运行库为每个委托类型提供了BeginInvoke和EndInvoke方法”。如果是这种情况,并且BeginInvoke甚至不是Delegate类中的一个方法(由CLR提供),它甚至有可能嘲笑它吗?有没有人有幸将BeginInvoke从委托类型中剔除出来?

+0

我不明白这一点。 BeginInvoke()充满了龙,它启动一个线程池线程来运行委托目标。线程是*难*。单元测试代码没有意义绕过代码失败的最可能且最不可知的原因。如果你找不到一个痣,一个假的或者任何其他的标签,那肯定是因为这些框架不希望你忽略你应该测试的最重要的东西。 –

回答

2

我并不真正了解微软的鼹鼠,但我试图通过微软假货实现同样的效果(实际上这是Microsoft Visual Studio 2012 Premium和Ultimate版本中的一个继承人)。

当我试图建立假组件(知道微软称之为假货和垫片,而不是痣和存根)我有以下警告:

Warning 1 Cannot generate stub for AssemblyUnderTest.FooDelegate: type is sealed. d:\Sources\Projects\PlayingWithMoles\PlayingWithMoles\Fakes\AssemblyUnderTest.fakes 
Warning 2 Cannot generate shim for AssemblyUnderTest.FooDelegate: type is a delegate. d:\Sources\Projects\PlayingWithMoles\PlayingWithMoles\Fakes\AssemblyUnderTest.fakes 

(要得到这样的警告,你应该关闭在附加诊断假货配置文件(我不知道该格式是假货和摩尔一样):

<Fakes xmlns="http://schemas.microsoft.com/fakes/2011/" **Diagnostic="true"**> 
    <Assembly Name="AssemblyUnderTest"/> 
</Fakes> 

但很可惜,这一警告明确指出,我们不能这样做,但我们能够避免这个问题的。通过转移到另一个异步API,例如Task Parallel Library a.k.a. TPL。对象本身表示异步操作作为第一个类对象,允许您在该字段中存储此“异步操作”,将其从方法返回或传递给它。这提高了可测试性很多,因为你可以很容易地嘲笑你实现与假的:

class SomeService 
{ 
    Task<string> GetSomeResult() 
    { 
    // Performing long-running operation to obtain the result 
    } 
} 

class YourServiceConsumer 
{ 
    private void YourMethod() 
    { 
    Task<string> task = service.GetSomeResult(); 
    } 
} 

比你可以轻松地与单独的界面提取您的依赖和它注入到你YourServiceConsumer或者使用Microsoft痣(或微软正版正货)假的而不添加额外的图层。