Question

Quelqu'un a-t-il des suggestions pour le test unitaire d'un complément d'application gérée pour Office? J'utilise NUnit, mais j'ai eu les mêmes problèmes avec MSTest.

Le problème est qu’un assemblage .NET est chargé dans l’application Office (dans mon cas, Word) et j’ai besoin d’une référence à cette instance de l’assembly .NET. Je ne peux pas simplement instancier l’objet car il n’aurait alors pas d’instance de Word pour faire des choses.

Maintenant, je peux utiliser Application.COMAddIns ("Nom du complément"). Interface d'objet pour obtenir une référence, mais cela me procure un objet COM qui est renvoyé via RequestComAddInAutomationService. Ma solution jusqu’à présent est que cet objet ait des méthodes proxy pour chaque méthode de l’objet .NET réel que je souhaite tester (toutes définies dans la compilation conditionnelle afin qu’elles disparaissent dans la version publiée).

L'objet COM (une classe VB.NET) a en fait une référence à l'instance du vrai complément, mais j'ai essayé de la renvoyer à NUnit et j'ai obtenu une belle erreur p / Invoke:

System.Runtime.Remoting.RemotingException: ce proxy distant n'a pas de récepteur de canal, ce qui signifie que le serveur n'a aucun canal de serveur enregistré en cours d'écoute ou que cette application n'a pas de canal client approprié pour communiquer avec le serveur. sur System.Runtime.Remoting.Proxies.RemotingProxy.InternalInvoke (IMethodCallMessage reqMcmMsg, Utilisation booléenne, EnvoiDispatchMessage, Int32 callType) à System.Runtime.Remoting.Proxies.RemotingProxy.Invoke (IMessage reqMsg) sur System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke (MessageData & amp; msgData, type Int32)

J'ai essayé de rendre visible le complément principal COM et le changement d'erreur:

System.InvalidOperationException: l'opération n'est pas valide en raison de l'état actuel de l'objet. à System.RuntimeType.ForwardCallToInvokeMember (String memberName, indicateurs BindingFlags, Object target, Int32 [] aWrapperTypes, MessageData & msgData)

Pendant que j'ai une solution de travail, c'est désordonné et met beaucoup de code de test dans le projet réel au lieu du projet de test - ce qui n'est pas vraiment la façon dont NUnit est censé fonctionner.

Était-ce utile?

La solution

Voici comment je l'ai résolu.

  1. À peu près tout dans mon complément provient de la méthode Click d'un bouton de l'interface utilisateur. J'ai changé toutes ces méthodes Click pour ne consister qu'en un simple appel sans paramètre.

  2. J'ai ensuite créé un nouveau fichier (Classe partielle) appelé EntryPoint, qui contenait beaucoup de très courts Subs Subs, chacun consistant généralement en un ou deux appels à des fonctions de travail paramétrées, de sorte que toutes les méthodes Click qui venaient d'être appelées ce fichier. Ainsi, par exemple, une fonction ouvre un document standard et appelle un "enregistrer sous". dans notre DMS. La fonction prend un paramètre du document à ouvrir et nous utilisons une douzaine de documents standard.

Donc j'ai

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

dans le ThisAddin puis

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

dans mon nouveau fichier EntryPoints.

  1. J'ajoute un nouveau fichier AddInUtilities contenant

    Interface publique IAddInUtilities

#Si DEBUG alors

Sub DocMemo()

#Fin si

End Interface


Public Class AddInUtilities
    Implements IAddInUtilities
    Private Addin as ThisAddIn

#Si DEBUG alors

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

#Fin si

 Friend Sub New(ByRef theAddin as ThisAddIn)
     Addin=theAddin
 End Sub
 End Class
  1. Je vais dans le fichier ThisAddIn et ajoute dans

    Utilitaires privés en tant qu'AddInUtilities

    Fonctions de substitution protégées RequestComAddInAutomationService () As Object     Si les utilitaires ne sont rien alors         utilities = New AddInUtilities (Me)     Fin si     Utilitaires de retour Fonction de fin

Et maintenant, il est possible de tester la fonction DocMemo () dans EntryPoints en utilisant NUnit, à peu près comme ceci:

<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 seule chose que vous ne pouvez pas ensuite tester à l'unité est les événements Click réels, car vous appelez dans EntryPoints d'une manière différente, c'est-à-dire via l'interface RequestComAddInAutomationService plutôt que via les gestionnaires d'événements.

Mais ça marche!

Autres conseils

Examinez les divers cadres moqueurs NMock , RhinoMocks , etc. pour simuler le comportement d'Office dans vos tests.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top