10 Stimmen

Wie vermeide ich die Verwendung von dynamischen, wenn mocking ein Excel.worksheet?

Ich versuche, eine Excel-Tabelle mit NSubstitute oder andere Mocking-Framework und MSTest (Visual Studio 2010) zu spiegeln. Ich bin nicht sicher, ob es einen besseren Weg als diese - und das funktioniert nicht ganz für die Prüfung:

Hier ist ein Beispiel (dies ist alles Prototyp-Code im Moment, und nicht sehr sauber):

int[] lowerBounds = { 1, 1 };
int[] lengths = { 2, 2 };

//Initialize a 1-based array like Excel does:
object[,] values = (object[,])Array.CreateInstance(typeof(object), lengths, lowerBounds);
values[1,1] = "hello";
values[2,1] = "world";      

//Mock the UsedRange.Value2 property
sheet.UsedRange.Value2.Returns(values); 

//Test:   
GetSetting(sheet, "hello").Should().Be("world");  //FluentAssertions

So weit, so gut: Dies funktioniert, wenn die GetSetting-Methode in demselben Projekt als mein Test. Jedoch wenn GetSetting in meinem VSTO Excel-Addin-Projekt ist, schlägt es mit dem folgenden Fehler in der ersten Zeile der GetSetting-Funktion fehl:

System.MissingMethodException: Error: Missing method 'instance object [MyExcel.AddIn] Microsoft.Office.Interop.Excel.Range::get_Value2()' from class 'Castle.Proxies.RangeProxy'.

Als Referenz greift GetSetting auf einen Wert aus SpalteA im Blatt zu und gibt den Wert in SpalteB zurück.

public static string GetSetting(Excel.Worksheet sheet, string settingName) {
  object[,] value = sheet.UsedRange.Value2 as object[,];
  for (int row = 1; row <= value.GetLength(1); row++) {
    if (value[1, row].ToString() == settingName)
      return value[2, row].ToString();
  }
  return "";
}

Interessant wird es schließlich, wenn ich die Signatur meiner Methode wie folgt neu definiere:
public static string GetSetting( dynamisch sheet, string settingName)
es funktioniert im VSTO-Projekt.

Was ist also los, und wie kann man so etwas am besten angehen?

Danke!

5voto

Jeremy Thompson Punkte 56282

Das VS2012-Update: Moq & Interop Types: funktioniert in VS2012, schlägt in VS2010 fehl?

Der erste: Es hat sich etwas geändert: Wie vermeide ich die Verwendung von dynamischen, wenn mocking ein Excel.worksheet?

Ich stieß auf das gleiche Problem Mocking Excel-Objekte mit NSubstitute. Die Dynamik löste das Problem genau so, wie Sie es beschrieben haben. Allerdings wollte ich die Grundursache zu finden.


Wenn Ihr Projekt einen Verweis auf Microsoft.Office.Interop.Excel.Extensions.dll müssen Sie prüfen, ob die Eigenschaft Interop-Typen einbetten sichtbar ist. Wenn dies der Fall ist, bedeutet dies, dass Sie auf .Net 4.0 abzielen (was ich anhand des dynamischen Schlüsselworts vermuten könnte).

Sie können das Testprojekt für .Net 4.0 belassen, aber Sie müssen das .Net-Framework des VSTO-Projekts auf 3.5 zurücksetzen. Dann werden Sie müssen Sie wahrscheinlich ein explizites Casting durchführen und Dinge vollständig qualifizieren, um um diese Fehler loszuwerden:

C# Office Excel Interop "Objekt enthält keine Definition für" Fehler Hier sind einige Beispiele:

.Net 4.0:

if (tmpsheetName == xlApp.ActiveSheet.Name)

.Net 3.5 entspricht

Worksheet activeSheet = (Worksheet)xlApp.ActiveSheet;
if (tmpsheetName == activeSheet.Name)

Ein weiteres Beispiel:

rn.Select();

.Net 4.0

xlApp.Selection.HorizontalAlignment = Constants.xlCenter; 
xlApp.Selection.Font.Bold = true;
xlApp.Selection.Merge();

.Net 3.5 entspricht

rn.HorizontalAlignment = Constants.xlCenter;
rn.Font.Bold = true;
rn.Merge();

Fahren Sie fort, alle .Net 3.5 vs 4.0 Syntaxfehler gemäß den obigen Beispielen zu beheben. Vergessen Sie nicht, die dynamic Parameter-Typ und ersetzen ihn durch den ursprünglichen Worksheet . Starten Sie schließlich den Test erneut und er wird bestehen!!!

Angesichts des ganzen Ärgers, den ich mit Microsoft.CSharp.DLL in dieser Gewinde Ich bin der Meinung, dass das Testen von VSTO .Net 4.0 Projekten mit Mocking Frameworks nicht funktioniert.

-1voto

tony722 Punkte 1905

Es hat sich herausgestellt, dass das Mocking von sehr komplexen COM-Interop-Objekten wie dem Excel-Objekt oder dem InDesign-Objekt mit einem der Castle-basierten Frameworks (nsubstitute, ninject usw.) keinen ausreichenden Leistungsschub bringt. Die Laufzeiten für Tests sind immer noch in Sekunden messbar. (Multipliziert man das mit Dutzenden oder Hunderten von Tests, sind die Unit-Tests immer noch zu langsam, um sie nach den TDD-Prinzipien des ständigen Testens auszuführen.)

Das Testen der Excel-Logik sollte dann als Integrationstest betrachtet werden, und als solcher sollte die Ausführung gegen das tatsächliche Excel-Objekt in Ordnung sein, wodurch Mocking in einem solchen Szenario nicht sehr nützlich ist. Die Ergebnisse sind viel nützlicher, wenn man gegen ein tatsächliches Objekt testet.

Das Testen auf einer Abstraktionsschicht, die zwischen Excel und der Anwendung liegt, würde ein schnelles Testen der Anwendungslogik ermöglichen. Und das Testen der Abstraktionsschicht zu Excel im Rahmen von Integrationstests sollte ausreichen, um die Anwendung gründlich zu testen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X