2012-07-24 14 views
6

Chcę kpić z Microsoft.Office.Interop.Excel.Range (i innych interfejsów Microsoft.Office.Interop.Excel), aby przetestować moją aplikację. Używam Moq 4.0.10827 z .NET 4 w C#.Jak wyśmiać Microsoft.Office.Interop.Excel.Range z Moq?

W moim badanej jednostki, próbuję skonfigurować zachowanie mock następująco:

 var range = new Mock<Microsoft.Office.Interop.Excel.Range>(); 
     range.Setup(r => r.get_Value(1)).Returns("Something"); 

     var classBeingTested = new MyClass(range.Object); 

W kodzie testowane urządzenie, używam zakresie następująco:

public MyClass(Range range) 
    { 
     var value = range[1].ToString(); 
    } 

Kiedy test jest uruchomiony, wytwarza się następujący wyjątek:

 Error: Missing method 'instance object [My.Example.Implementation.MyClass] Microsoft.Office.Interop.Excel.Range::get__Default(object,object)' from class 'Castle.Proxies.RangeProxy'. 

Jak mogę wdrożyć ten mockin g z powodzeniem? Zdaję sobie sprawę, że izolowanie funkcji Excel Interop z wzorcem takim jak https://stackoverflow.com/a/9486226/1548950 jest potencjalnym rozwiązaniem; Byłbym jednak bardziej zadowolony z możliwości tworzenia makr z interfejsów Microsoft.Office.Interop.Excel.

EDIT: Więcej szczegółów na ten temat

OK, to jest dziwne. Stworzyłem projekt, aby przetestować sugestię autorstwa jimmy_keen. To działa. Jednak, kiedy używać tego samego sugestię, aby przetestować projekt miałem problemy z, rzuca następujący wyjątek:

Error: Missing method 'instance object [My.Example.Implementation.MyClass] Microsoft.Office.Interop.Excel.Range::get__Default(object,object)' from class 'Castle.Proxies.RangeProxy'. 

Ponieważ propozycja jimmy_keen pracował dobrze na innych projektach, zacząłem podejrzewać, że coś jest nie tak z projekt Testuję kod za pomocą. Więc stworzyliśmy testową rozwiązanie, które demonstruje problem w szczegółach: http://www7.zippyshare.com/v/70834394/file.html

Korzeń Problem wydaje się, że projekt zawiera inną klasę (który nie jest testowane urządzenie) z zasadniczo następujący kod:

using Microsoft.Office.Interop.Excel; 
namespace Project 
{ 
    public class UnTestedClass 
    { 
     public UnTestedClass(Worksheet sheet) 
     { 
      var foo = sheet.Range["Description"].Column; 
     } 
    } 
} 

Nie rozumiem, dlaczego to powoduje problem, ponieważ w ogóle nie używam UnTestedClass w teście jednostkowym. Czy brakuje mi czegoś, w jaki sposób powinienem użyć Moq, czy też natknąłem się na błąd?

+0

+1 To dziwne, zgaduję, że ma to coś wspólnego z obiektami COM. Jak tylko odwołam się do programu Excel, nie mogę już odwoływać się do mojej biblioteki Moq ... Dziwne ... – jsmith

+0

Po wykonaniu niektórych prac, zamierzam teraz wyizolować funkcjonalność Microsoft.Office.Interop.Excel z własnej niestandardowe klasy i interfejsy zamiast kpić bezpośrednio z Microsoft.Office.Interop.Excel. * Podczas gdy odpowiedź na to pytanie rozwiązuje natychmiastowe problemy, kpiąc z Microsoft.Office.Interop.Excel. * Ostatecznie zaczęło wymagać zbyt wiele pracy konfiguracyjnej, aby była użyteczna. –

Odpowiedz

5

Twój kod dostępu podziałowe, a to, co trzeba kpić:

var range = new Mock<Microsoft.Office.Interop.Excel.Range>(); 
range.Setup(r => r[1, It.IsAny<object>()]).Returns("something"); 

Range indekser Zauważ, że faktycznie ma dwa parametry - stąd It.IsAny<object>() wymuszenie w połączeniu.

+0

Dzięki, przetestowałem to i działa w niektórych przypadkach. Jednak test jednostkowy, nad którym pracuję, wciąż uparcie odmawia pracy. Zobacz rozwiązanie testowe, które przesłałem pod adresem http://www7.zippyshare.com/v/70834394/file.html –

+2

@LauriHarpf: jest to interesujące. Najwyraźniej jest to "problem" z wygenerowanym przez kompilator kodem.Interfejs typu 'Range' wygenerowany przez kompilator w twoim * Project * ma dodatkową własność (' Column', a mianowicie). Nie mam pojęcia, jak to może być problematyczne dla Castle ... ale to COM. Jeśli na przykład sprawdzisz swoje złożenia za pomocą ILSpy, zobaczysz, co mam na myśli. Kod wygenerowany przez kompilator różni się (nawet jeśli klasy są takie same) i to musi być problem. Zauważ, że jeśli wpiszesz 'range.Setup (r => r.Column). Zwraca (0);' ten test również przejdzie. –

+1

Doskonale, dzięki! Końcówka ILSpy również była złota; w moim prawdziwym projekcie widzę inne dodatkowe właściwości pojawiające się obok kolumny. Obecne są "Kolumna", "Kolumny", "Wiersz", "Wiersze" i "Wartość". Takie zachowanie prawdopodobnie sprawi, że jakiekolwiek testy jednostkowe, które piszę, są dość kruche, ponieważ w każdej chwili mogą pojawić się nowe właściwości i coś złamać. W każdym razie, stosując swoje wskazówki i ostrożnie kpiąc sobie z wszystkich dodatkowych właściwości, które to działa, więc oznaczając jako odpowiedź. Dziękuję Panu! –