5

I need end-to-end guidance on this topic.

Here is a scenario: I have a Word AddIn written in C#, in which I have some interop interaction with Excel. I need to unit-test that.

How?

There is no usable guidance on the topic, except this: http://clear-lines.com/blog/post/unit-testing-vsto-projects.aspx

Thanks Dragan

2

The answer to almost all questions about unit testing is "decouple from dependencies".

Refactor your code to decouple the logic (which you want to test) from the interactions with with Excel.

Remember that unit tests should answer the question "does the code I am writing do what I intend it to do" and not "does my program work properly" - that's for integration tests.

1

I haven't done this type of testing, what I would recommend is looking into how you can write office macros that utilise the functions of your add-in to test it's functionality. You should be able to add vba command buttons to a spreadsheet or document or the word toolbar that runs your tests.

I am assuming that as you are testing and adding in VSTO, you have a good working knowledge of the excel and word APIs as that would be required.

  • I'm trying to unit test it using VS and C# – Dragan Panjkov Feb 5 '12 at 8:53
  • You should pronely use VB.net otherwise you will have lots of Type.missing calls. If you are going to call from VS, you should use the COM api to drive word and your add-in. – Bruce McLeod Feb 5 '12 at 21:11
  • Re. Type.missing : I use .NET 4.0, so luckily I don't have those in my code. – Dragan Panjkov Feb 6 '12 at 8:29
0

OfficeAddin/ThisAddIn.cs

using System;
using Word = Microsoft.Office.Interop.Word;
using Office = Microsoft.Office.Core;
using System.Runtime.InteropServices;

namespace OfficeAddIn
{
    public partial class ThisAddIn
    {
        public static string OfficeAddress = @"Path\To\Word.doc";
        public void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
            CallflowTester.ThisAddIn_Startup(sender, e);
        }

        private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
        {
        }

        private AddinUtilities utilities;
        protected override object RequestComAddInAutomationService()
        {
            if (utilities == null)
                utilities = new AddinUtilities();
            return utilities;
        }

        #region VSTO generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InternalStartup()
        {
            this.Startup += new System.EventHandler(ThisAddIn_Startup);
            this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
        }

        #endregion

    }
}

OfficeAddin/AddinUtilities.cs

using System;
using System.Runtime.InteropServices;
using Word = Microsoft.Office.Interop.Word;

namespace OfficeAddIn
{
    [ComVisible(true)]
    [Guid("274069A2-1895-4B18-BFEA-125FE2D89D02")]
    [InterfaceType(ComInterfaceType.InterfaceIsDual)]
    public interface IAddInUtilities
    {
        // Setting Up
        void runSetupFunction(ref Word.Application a);

        // Functional Test
        int runAddInFunction(int page, int item);
    }

    [ComVisible(true)]
    [Guid("A18CDCA6-F138-44D4-8BD9-3EC68FE8B546")]
    [ClassInterface(ClassInterfaceType.None)]
    public class AddinUtilities :
    StandardOleMarshalObject,
    IAddInUtilities
    {
        // Setting Up
        public void runSetupFunction(ref Word.Application a) => yourSetupFunction(a);

        // Functional Test
        public int runAddInFunction(int page, int item) => yourAddInFunction(page, item);
    }
}

OfficeAddinTests/ThisAddInTests.cs

using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using Word = Microsoft.Office.Interop.Word;
using Office = Microsoft.Office.Core;

namespace OfficeAddIn_Tests
{
    [TestClass]
    public class AudioTTSTests
    {
        private static string wordAddress = @"Address/To/Word.doc";

        #region Test Setup

        private static Word.Application word = null;
        public static Word.Document wdoc = null;
        static ECCO_Callflow_Tools.IAddInUtilities utilities = null;

        [ClassInitialize()]
        public static void This_AddIn_Initialize(TestContext t)
        {
            word = new Word.Application();
        }

        public static void SetupDocuments()
        {
            try {
                object addInName = "TheNameOfYOurAddin";
                wdoc = word.Documents.Open(wordAddress);
                Office.COMAddIn addIn = word.COMAddIns.Item(ref addInName);

                while (utilities == null)
                {
                    utilities = (OfficeAddIn.IAddInUtilities)addIn.Object;
                    System.Threading.Thread.Sleep(100);
                }
                utilities.runSetupFunction();
            }
            catch (Exception ex) {
                wdoc?.Close();
                word.Quit();
                word = null;
                utilities = null;
                GC.Collect();
                throw ex;
            }
        }

        [TestCleanup()]
        public void TestCleanup()
        {
            if (word != null)
            {
                word.Quit();
                word = null;
            }
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }

        #endregion

        [TestMethod()]
        public void AudioTTSTests_Setup()
        {
            SetupDocuments();
            utilities.runAddInFunction();
        }
    }
}

Here are some links to get started. You need understand how to call code from other applications here https://msdn.microsoft.com/en-us/library/bb608621.aspx

There are some errors if you are trying to call from an external application so this link I found helpful https://stackoverflow.com/questions/10875278/vsto-add-ins-comaddins-and-requestcomaddinautomationservice

  • Please update your answer to include the key information from the links in your answer. Link-only answers usually get deleted. – Kate Paulk Sep 22 '16 at 11:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.