2008-09-24 22 views
5

¿Alguien ha recibido alguna sugerencia para probar en unidades un complemento de aplicación administrada para Office? Estoy usando NUnit pero tuve los mismos problemas con MSTest.Pruebas unitarias de .NET Add-In para Microsoft Office

El problema es que hay un ensamblado .NET cargado dentro de la aplicación de Office (en mi caso, Word) y necesito una referencia a esa instancia del ensamblado .NET. No puedo simplemente crear una instancia del objeto porque no tendría una instancia de Word para hacer las cosas.

Ahora, puedo usar Application.COMAddIns ("Nombre del complemento"). Interfaz de objeto para obtener una referencia, pero me da un objeto COM que se devuelve a través de RequestComAddInAutomationService. Mi solución hasta ahora es que ese objeto tenga métodos proxy para cada método en el objeto .NET real que quiero probar (todo configurado en compilación condicional para que desaparezca en la versión lanzada).

El objeto COM (una clase VB.NET) en realidad tiene una referencia a la instancia de lo real complemento, pero he intentado devolver esa de NUnit y me dieron un buen p/error Invocar:

System.Runtime.Remoting.RemotingException: este proxy remoto no tiene sumidero de canal, lo que significa que el servidor no tiene canales de servidor registrados que están escuchando, o esta aplicación no tiene un canal de cliente adecuado para comunicarse con el servidor. en System.Runtime.Remoting.Proxies.RemotingProxy.InternalInvoke (IMethodCallMessage reqMcmMsg, Boolean useDispatchMessage, Int32 CALLTYPE) en System.Runtime.Remoting.Proxies.RemotingProxy.Invoke (I-Mensaje reqMsg) en System.Runtime.Remoting.Proxies. RealProxy.PrivateInvoke (MessageData & MSGDATA, el tipo Int32)

intenté hacer el principal complemento COM visible y el error cambios:

System.InvalidOperationException: Operación no es válida debido al estado actual del objeto . en System.RuntimeType.ForwardCallToInvokeMember (String memberName, banderas BindingFlags, meta objeto, Int32 [] aWrapperTypes, MessageData & MSGDATA)

Aunque no tengo una solución alternativa, es desordenado y pone un montón de código de prueba en el proyecto real en lugar del proyecto de prueba, que no es realmente la forma en que NUnit debe funcionar.

Respuesta

2

Así lo resolví.

  1. Casi todo en mi complemento se ejecuta desde el método Click de un botón en la interfaz de usuario. He cambiado todos los métodos de Click para que consistan solo en una llamada simple y sin parámetros.

  2. Luego creé un nuevo archivo (Clase parcial) llamado EntryPoint que tenía muchos Friend Subs muy cortos, cada uno de los cuales solía ser una o dos llamadas a funciones de usuario parametrizadas, de modo que todos los métodos Click recién llamaban a este archivo. Entonces, por ejemplo, hay una función que abre un documento estándar y llama a "guardar como" en nuestro DMS. La función toma un parámetro de qué documento abrir, y hay un par de docenas de documentos estándar que usamos.

Así que tienen

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

en el ThisAddIn y luego

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

en mi nuevo archivo de puntos de entrada.

  1. agrego un nuevo archivo AddInUtilities que tiene

    interfaz pública 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. voy al archivo ThisAddIn y añadir en

    utilidades privadas como AddInUtilities

    Protegido anula la diversión cción RequestComAddInAutomationService() como objeto Si Utilities es nada, entonces utilidades = Nuevas AddInUtilities (Me) final si utilidades de retorno End Function

y ahora es posible poner a prueba la función DocMemo() en puntos de entrada utilizando NUnit, algo como esto:

<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 

la única cosa que no puede entonces prueba de la unidad son los hechos reales Click, porque estás poniendo en puntos de entrada de una manera diferente, es decir, a través de la RequestComAdd InAutomationService interfaz en lugar de a través de los controladores de eventos.

¡Pero funciona!

2

Considere los diversos marcos de burla NMock, RhinoMocks, etc. para simular el comportamiento de Office en sus pruebas.

+1

¡Tendría que burlarme de Office para que funcione! –

+0

@RichardGadsden Sí, está bien y lo hice para Excel usando NSubstitute, no fue tan difícil al final. –

Cuestiones relacionadas