При издевательстве Workbook-> Worksheets: переменная 'p' типа 'Microsoft.Office.Interop.Excel.Workbook' ссылается на область действия '', но она не определена - PullRequest
0 голосов
/ 15 февраля 2019

Я только начинаю изучать, как использовать модульное тестирование с NUnit и как использовать имитацию для подделки объектов, которые мне нужно протестировать.

В настоящее время я работаю с проектом, который реализует VSTO ExcelАддин и хотел бы начать использовать модульные тесты с этим проектом.

Итак, у меня есть функция, которая принимает рабочую книгу в качестве параметра и возвращает список соответствующих рабочих листов, которые я хочу обработать.Эту функцию я бы хотел проверить.Мне «просто» нужно подделать имена рабочих листов, так как эта функция только перебирает все рабочие таблицы и проверяет их имена.

При поиске в интернет-ресурсах я пытался создать следующее решение, пытаясь подделать рабочую книгу с помощьюсписок рабочих листов со списком имен «SheetNames», который имеет тип List:

        var fakeWorksheetList = new List<Excel.Worksheet>();
        foreach (string sheetName in SheetNames)
        {
            var sheet = Mock.Of<Excel.Worksheet>();
            sheet.Name = sheetName;
            fakeWorksheetList.Add(sheet);
        }

        var fakeWorkbook = new Mock<Excel.Workbook>();
        fakeWorkbook.Setup(p => p.Worksheets.GetEnumerator())
            .Returns(() => fakeWorksheetList.GetEnumerator());

Но при запуске тестового кода я получаю следующее сообщение об ошибке:

variable "p" of type "Microsoft.Office.Interop.Excel.Workbook" referenced from scope "", but it is not defined

Чтоя делаю неправильноПочему лямбда-выражение в Setup () выдает мне такое сообщение об ошибке?Есть ли лучший способ подделать Список рабочих листов?

Пожалуйста, прости меня, если я показываю некоторое непонимание, поскольку я действительно только начинаю с насмешливой темы.

Это функция, которую яхочу протестировать, что мне нужно в моей надстройке, чтобы получить все рабочие листы, с которыми должна работать моя надстройка:

    public static Dictionary<int, Excel.Worksheet> GetApplicableYearSheets(Excel.Workbook Workbook, int iCurrentYear = 0)
    {
        if (iCurrentYear <= 0)
            iCurrentYear = DateTime.Now.Year;

        int iFromYear = iCurrentYear - 2;
        Dictionary<int, Excel.Worksheet> YearSheets = new Dictionary<int, Excel.Worksheet>();

        for (int iNr = 1; iNr <= Workbook.Worksheets.Count; iNr++)
        {
            int iYear = 0;
            string sWorksheetName = Workbook.Worksheets[iNr].Name;
            if ((sWorksheetName.Trim().Length == 4) && (int.TryParse(sWorksheetName, out iYear)))
            {
                if ((iYear >= iFromYear) && (iYear <= iCurrentYear))
                    YearSheets.Add(iYear, Workbook.Worksheets[iNr]);
            }
        }

        return YearSheets;
    }

Список имен листов, которые я хочу использовать для тестирования, например:

        List<string> SheetNames = new List<string>()
        {
            "2012",
            "2013",
            "2014",
            "2015",
            "2016",
            "2017",
            "2018",
            "2019",
            "Test",
            "Spezialfälle"
        };

Мой план состоял в том, чтобы протестировать вызов этой функции с помощью поддельной книги fakeWorkbook, например, следующим образом:

Assert.That(InvoicingUtils.GetApplicableYearSheets(FakeWbFullNames, iCurrentYear: 2019), Has.Exactly(3).Items);

и т. Д.

1 Ответ

0 голосов
/ 17 февраля 2019

Я думаю, что есть лучший и более элегантный способ написания кода для насмешек, но это работает для меня.
Пожалуйста, обратите внимание:
- я использую Moq в качестве среды для насмешек.Я полагаю, вы используете тот же
- я изменил тип возвращаемого вами метода на IDictionary, так как у меня были некоторые проблемы только с Dictionary

Код:
- Для инициализации тестовых листов вы можете использовать цикл.Я просто упростил задачу и создал всего два листа без каких-либо петель.
- я думаю, что вы сможете заставить его работать всего за несколько установок объекта workbook, но мне это нравится ( просто персонально).ничего предпочтения )
- Как видите, вся логика запускается на объекте sheets.Обычно я получаю индекс из производственного кода, вычитая -1, чтобы получить нулевой индекс, сохраняю его в моей переменной sheetIndex и затем возвращаю обратно поддельный лист из worksheets коллекции

using System.Collections.Generic;
using Excel = Microsoft.Office.Interop.Excel;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;

namespace ExcelMocking.Tests
{
    [TestClass]
    public class UnitTest1
    {
        private List<Excel.Worksheet> worksheets = new List<Excel.Worksheet>();

        [TestMethod]
        public void TestMethod1()
        {
            var sheet = new Mock<Excel.Worksheet>();
            sheet.SetupGet(w => w.Name).Returns("2012");
            worksheets.Add(sheet.Object);

            sheet = new Mock<Excel.Worksheet>();
            sheet.SetupGet(w => w.Name).Returns("2013");
            worksheets.Add(sheet.Object);

            var sheetIndex = 0;
            var sheets = new Mock<Excel.Sheets>();
            sheets.Setup(s => s.Count).Returns(() => worksheets.Count);
            sheets.Setup(s => s[It.IsAny<object>()]).Callback<object>((theSheetIndex) =>
            {
                // getting the real sheet index from the production code that starts from 1
                // and simple subtracting -1 to get zero based index
                sheetIndex = (int)theSheetIndex;
                sheetIndex--;
            }).Returns(() => worksheets[sheetIndex]);

            sheets.Setup(s => s.GetEnumerator()).Returns(() => worksheets.GetEnumerator());
            sheets.As<Excel.Sheets>().Setup(s => s.GetEnumerator()).Returns(() => worksheets.GetEnumerator());

            var workbook = new Mock<Excel.Workbook>();
            workbook.Setup(w => w.Worksheets).Returns(sheets.Object);            

            IDictionary<int, Excel.Worksheet> result = ExcelMocking.Class1.GetApplicableYearSheets(workbook.Object);
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...