6

有没有人对 Office 托管应用程序加载项进行单元测试有任何建议?我正在使用 NUnit,但我在使用 MSTest 时遇到了同样的问题。

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

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

COM 对象(一个 VB.NET 类)实际上具有对真实加载项实例的引用,但我尝试将其返回给 NUnit,但我得到了一个不错的 p/Invoke 错误:

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

我尝试使主加载项 COM 可见并且错误更改:

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

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

4

2 回答 2

3

这就是我解决它的方法。

  1. 我的加载项中的几乎所有内容都从 UI 中按钮的 Click 方法运行。我已将所有这些 Click 方法更改为仅包含一个简单的无参数调用。

  2. 然后,我创建了一个名为 EntryPoint 的新文件(部分类),其中包含许多非常短的 Friend Sub,每个通常都是对参数化工作函数的一两次调用,因此所有 Click 方法都只调用到该文件中。因此,例如,有一个函数可以打开一个标准文档并将“另存为”调用到我们的 DMS 中。该函数接受打开哪个文档的参数,我们使用了几十个标准文档。

所以我有

Private Sub btnMemo_Click(ByVal Ctrl As Microsoft.Office.Core.CommandBarButton, ByRef CancelDefault As Boolean) Handles btnMemo.Click
    DocMemo()
End Sub

在 ThisAddin 然后

Friend Sub DocMemo()
    OpenDocByNumber("Prec", 8862, 1)
End Sub

在我的新入口点文件中。

  1. 我添加了一个新的 AddInUtilities 文件,该文件具有

    公共接口 IAddInUtilities

#If DEBUG Then

Sub DocMemo()

#End If

End Interface


Public Class AddInUtilities
    Implements IAddInUtilities
    Private Addin as ThisAddIn

#If DEBUG Then

Public Sub DocMemo() Implements IAddInUtilities.DocMemo
    Addin.DocMemo()
End Sub

#End If

 Friend Sub New(ByRef theAddin as ThisAddIn)
     Addin=theAddin
 End Sub
 End Class
  1. 我转到 ThisAddIn 文件并添加

    私有实用程序作为 AddInUtilities

    Protected Overrides Function RequestComAddInAutomationService() As Object If utility is Nothing Then utility = New AddInUtilities(Me) End If Return utility End Function

现在可以使用 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

唯一不能进行单元测试的是实际的 Click 事件,因为您以不同的方式调用 EntryPoints,即通过 RequestComAddInAutomationService 接口而不是通过事件处理程序。

但它有效!

于 2009-04-03T11:32:37.697 回答
2

考虑使用各种模拟框架NMockRhinoMocks等来伪造 Office 在您的测试中的行为。

于 2008-09-24T11:19:14.243 回答