Vb.net Microsoft Office.NET加载项的单元测试

Vb.net Microsoft Office.NET加载项的单元测试,vb.net,ms-office,add-in,Vb.net,Ms Office,Add In,有人对Office托管应用程序外接程序的单元测试有什么建议吗?我正在使用NUnit,但MSTest也有同样的问题 问题是Office应用程序(在我的例子中是Word)中加载了一个.NET程序集,我需要一个对该.NET程序集实例的引用。我不能只是实例化对象,因为这样它就不会有Word的实例来做事情 现在,我可以使用Application.COMAddIns(“addin的名称”).Object接口来获取引用,但这会获得一个通过RequestComAddInAutomationService返回的C

有人对Office托管应用程序外接程序的单元测试有什么建议吗?我正在使用NUnit,但MSTest也有同样的问题

问题是Office应用程序(在我的例子中是Word)中加载了一个.NET程序集,我需要一个对该.NET程序集实例的引用。我不能只是实例化对象,因为这样它就不会有Word的实例来做事情

现在,我可以使用Application.COMAddIns(“addin的名称”).Object接口来获取引用,但这会获得一个通过RequestComAddInAutomationService返回的COM对象。到目前为止,我的解决方案是让该对象对我要测试的真实.NET对象中的每个方法都有代理方法(所有方法都在条件编译下设置,以便它们在发布的版本中消失)

COM对象(一个VB.NET类)实际上有一个对实际外接程序实例的引用,但我尝试将其返回给NUnit,结果出现了一个很好的p/Invoke错误:

System.Runtime.Remoting.RemotingException:此远程代理没有通道接收器,这意味着服务器没有正在侦听的已注册服务器通道,或者此应用程序没有合适的客户端通道与服务器对话。 at System.Runtime.Remoting.Proxy.RemotingProxy.InternalInvoke(IMethodCallMessage reqMcmMsg、布尔useDispatchMessage、Int32 callType) at System.Runtime.Remoting.proxy.RemotingProxy.Invoke(IMessage reqMsg) at System.Runtime.Remoting.proxy.RealProxy.PrivateInvoke(MessageData&msgData,Int32类型)

我尝试使主加载项COM可见,但错误发生了更改:

System.InvalidOperationException:由于对象的当前状态,操作无效。 位于System.RuntimeType.ForwardCallToInvokeMember(字符串memberName、BindingFlags标志、对象目标、Int32[]aWrapperTypes、MessageData和msgData)


虽然我有一个解决办法,但它很混乱,在真实的项目中而不是在测试项目中放置了大量的测试代码——这并不是NUnit真正的工作方式。

考虑各种模拟框架等,在测试中伪造Office的行为

我就是这样解决的

  • 我的外接程序中的几乎所有内容都是通过UI中按钮的单击方法运行的。我已经改变了所有那些Click方法,只包含一个简单的、无参数的调用

  • 然后我创建了一个名为EntryPoint的新文件(分部类),它有很多非常短的Friend Sub,每个Sub通常是一个或两个对参数化工作函数的调用,因此所有的Click方法都被调用到此文件中。例如,有一个函数打开一个标准文档,并在DMS中调用“另存为”。该函数获取打开哪个文档的参数,我们使用几十个标准文档

  • 所以我有

    Private Sub btnMemo_Click(ByVal Ctrl As Microsoft.Office.Core.CommandBarButton, ByRef CancelDefault As Boolean) Handles btnMemo.Click
        DocMemo()
    End Sub
    
    在这个世界上

    Friend Sub DocMemo()
        OpenDocByNumber("Prec", 8862, 1)
    End Sub
    
    在我的新入口点文件中

  • 我添加了一个新的AddInUtilities文件,该文件

    公共接口实用程序

  • #如果是调试,则

    Sub DocMemo()
    
    Public Sub DocMemo() Implements IAddInUtilities.DocMemo
        Addin.DocMemo()
    End Sub
    
    #如果

    End Interface
    
    
    Public Class AddInUtilities
        Implements IAddInUtilities
        Private Addin as ThisAddIn
    
     Friend Sub New(ByRef theAddin as ThisAddIn)
         Addin=theAddin
     End Sub
     End Class
    
    #如果是调试,则

    Sub DocMemo()
    
    Public Sub DocMemo() Implements IAddInUtilities.DocMemo
        Addin.DocMemo()
    End Sub
    
    #如果

    End Interface
    
    
    Public Class AddInUtilities
        Implements IAddInUtilities
        Private Addin as ThisAddIn
    
     Friend Sub New(ByRef theAddin as ThisAddIn)
         Addin=theAddin
     End Sub
     End Class
    
  • 我转到ThisAddIn文件并加载项

    作为附加设施的私人公用事业

    受保护的重写函数RequestComAddInAutomationService()作为对象 如果公用事业一文不值 实用程序=新的附加功能(Me) 如果结束 返回实用程序 端函数

  • 现在可以使用NUnit在EntryPoints中测试DocMemo()函数,如下所示:

    <TestFixture()> Public Class Numbering
    
    Private appWord As Word.Application
    Private objMacros As Object
    
    <TestFixtureSetUp()> Public Sub LaunchWord()
        appWord = New Word.Application
        appWord.Visible = True
    
        Dim AddIn As COMAddIn = Nothing
        Dim AddInUtilities As IAddInUtilities
        For Each tempAddin As COMAddIn In appWord.COMAddIns
            If tempAddin.Description = "CobbettsMacrosVsto" Then
                AddIn = tempAddin
            End If
        Next
        AddInUtilities = AddIn.Object
        objMacros = AddInUtilities.TestObject
    
    
    End Sub
    
    <Test()> Public Sub DocMemo()
    
    
        objMacros.DocMemo()
    End Sub
    
    <TestFixtureTearDown()> Public Sub TearDown()
        appWord.Quit(False)
    End Sub
    
    End Class
    
    公共类编号
    私有appWord作为Word.Application
    私有对象作为对象
    公共子启动字()
    appWord=新单词。应用程序
    appWord.Visible=True
    Dim AddIn As COMAddIn=无
    作为IAddInUtilities的Dim附加功能
    对于appWord.COMAddIns中的每个tempadin作为COMAddIn
    如果tempAddin.Description=“Cobbettsmarosvsto”,则
    AddIn=tempAddin
    如果结束
    下一个
    AddInUtilities=附加对象
    objMacros=AddInUtilities.TestObject
    端接头
    公共分文件
    objMacros.DocMemo()
    端接头
    公共子拆卸()
    appWord.Quit(False)
    端接头
    末级
    
    唯一不能进行单元测试的是实际的单击事件,因为您以不同的方式调用入口点,即通过RequestComAddInAutomationService接口而不是通过事件处理程序


    但它是有效的

    @RichardGadsden是的&我已经用NSubstitute为Excel做了这件事,但最终并没有那么难。