Модульное тестирование надстройки .NET для Microsoft Office

StackOverflow https://stackoverflow.com/questions/126526

  •  02-07-2019
  •  | 
  •  

Вопрос

У кого-нибудь есть какие-либо предложения по модульному тестированию надстройки управляемого приложения для Office?Я использую NUnit, но у меня были те же проблемы с MSTest.

Проблема в том, что внутри приложения Office загружена сборка .NET (в моем случае Word), и мне нужна ссылка на этот экземпляр сборки .NET.Я не могу просто создать экземпляр объекта, потому что тогда у него не было бы экземпляра Word, с которым можно было бы что-то делать.

Теперь я могу использовать приложение.COMAddIns ("Имя надстройки").Объектный интерфейс для получения ссылки, но это возвращает мне COM-объект, который возвращается через RequestComAddInAutomationService.Мое решение на данный момент заключается в том, чтобы у этого объекта были прокси-методы для каждого метода в реальном.ЧИСТЫЙ объект, который я хочу протестировать (все задано при условной компиляции, чтобы они исчезли в выпущенной версии).

COM-объект (a VB.NET class) на самом деле имеет ссылку на экземпляр реальной надстройки, но я попытался просто вернуть это в NUnit и получил приятную ошибку p / Invoke:

Система.Среда выполнения.Удаленное взаимодействие.Исключение RemotingException :Этот удаленный прокси-сервер не имеет приемника каналов, что означает, что либо на сервере нет зарегистрированных серверных каналов, которые прослушивают, либо у этого приложения нет подходящего клиентского канала для связи с сервером.в System.Runtime.Удаленный доступ.Прокси.RemotingProxy.InternalInvoke(IMethodCallMessage reqMcmMsg, логическое значение useDispatchMessage, тип вызова Int32) в System.Runtime.Удаленное взаимодействие.Прокси.RemotingProxy.Вызвать (запрос iMessage) в System.Runtime.Удаленный доступ.Прокси.RealProxy.PrivateInvoke(MessageData& msgData, тип Int32)

Я попытался сделать основную надстройку COM видимой, и ошибка изменилась:

Система.Исключение InvalidOperationException :Операция недопустима из-за текущего состояния объекта.в System.RuntimeType.ForwardCallToInvokeMember(Строковое имя члена, флаги BindingFlags, целевой объект, Int32[] aWrapperTypes, MessageDataи msgData)

Хотя у меня есть обходной путь, он грязный и помещает много тестового кода в реальный проект вместо тестового проекта - что на самом деле не так, как должен работать NUnit.

Это было полезно?

Решение

Вот как я решил эту проблему.

  1. Практически все в моей надстройке запускается методом нажатия кнопки в пользовательском интерфейсе.Я изменил все эти методы Click, чтобы они состояли только из простого вызова без параметров.

  2. Затем я создал новый файл (частичный класс) с именем EntryPoint, в котором было множество очень коротких вспомогательных файлов Friend, каждый из которых обычно представлял собой один или два вызова параметризованных рабочих функций, так что все методы 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

в моем новом файле EntryPoints.

  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 и добавляю

    Частные утилиты Как дополнительные возможности

    Защищенный Переопределяет функцию RequestComAddInAutomationService() Как объект Если утилиты Ничего не значат, то утилиты = Новые дополнительные возможности (Me) Завершить, если Вернуть утилиты Завершить функцию

И теперь можно протестировать функцию DocMemo() в точках входа, используя NUnit, что-то вроде этого:

<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, потому что вы вызываете точки входа другим способом, т. Е. через интерфейс RequestComAddInAutomationService, а не через обработчики событий.

Но это работает!

Другие советы

Рассмотрим различные насмешливые фреймворки Нмок, Носороги, и т.д.имитировать поведение Office в ваших тестах.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top