Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Moq-Framework: wie geht Weakmatching?
spike24
myCSharp.de - Member



Dabei seit:
Beiträge: 451
Herkunft: Steiermark Österreich

Themenstarter:

Moq-Framework: wie geht Weakmatching?

beantworten | zitieren | melden

Hallo Ihr,

Ich glaube es heist Weakmatching, Ich möchte das Parameter nur teilweise Matchen.

Ich habe eine Klasse die als Identifier einen Guid erstellt.
Guid ProcessArguments.Identifier;
Diese Klasse hat auch noch eine zweite Property
List<string> ProcessArguments.Strings


In meiner TestKlasse bereichte ich eine Instance auf um sie der Method Setup des Moq frameworks

ProcessArgument arg = new ProcessArgument();
// der Identifier wird im ctor zugewiesen (eine Guid erstellt)
arg.Strings.Add("test");


Die Methode die ich testen möchte erstellt ebenfalls ein ProcessArgument,
klarerweise mit einer anderen Guid.

Wie kann ich nun das Moq framework aufsetzten dass nur die Gleichheit der Property Strings überprüft wird?

Ich verbringe leider schon realtive viel Zeit damit, wäre net wenn Ihr mir dabei helfen könntet!?

mbg
Robert Rossegger



Noch ein bisschen Code, zum zeigen was ich habe, aber leider nicht funktioniert.

mTestClassMock.Setup(mock => mock.MethodToTest(It.Is<ProcessArgument>(argument => EqualsProcessArgument(argument, processModificationEventArgs))
)).Returns(bla));


private static bool EqualsProcessArgument(ProcessArgument processModificationArgument, ProcessArgument processModificationArgumento)
{
// wird nie aufgerufen!
  return true;
}


http://code.google.com/p/moq/wiki/QuickStart
diese seite sah für mich am richtigsten aus, allerdings habe ich nicht mal annähernd das gleiche Verhalten.

Moq Version:
4.0.10827.0

// Edit Fehler behoben, danke fürs genaue lesen
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von spike24 am .
mbg
Rossegger Robert
mehr fragen mehr wissen

Montag morgen ist die beste Zeit um eine erfolgreiche Woche zu beginnen
private Nachricht | Beiträge des Benutzers
gfoidl
myCSharp.de - Team

Avatar #avatar-2894.jpg


Dabei seit:
Beiträge: 7563
Herkunft: Waidring

beantworten | zitieren | melden

Hallo spike24,

wenn ich dich richtig verstanden habe kannst du mit Callbacks arbeiten und dort das Argument behandeln.


mfG Gü
Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"
private Nachricht | Beiträge des Benutzers
zommi
myCSharp.de - Member

Avatar #avatar-2617.png


Dabei seit:
Beiträge: 1380
Herkunft: Berlin

beantworten | zitieren | melden

Hi spike24,
  1. Vielleicht ist es nur ein Fehler für die Aufbereitung hier fürs Forum, aber beachte:
    EqualsProcessModificationArgument != EqualsProcessArgument
    Du rufst die untere Methode überhaupt nicht.
  2. Regel für Unit-Tests: Abhängigkeiten zur Umgebung wegmocken! Deine Klasse ist anscheinend hart an einen bestimmen GUID-Generator gekoppelt.
    Wenn du diese Kopplung loser gestaltest, also ein Interface für GUID-Generatoren erstellst, und deinen ProcessArguments einen solchen GUID-Generator mitgibst. (vielleicht auch als statisches feld) Dann kannst du die GUID-Erzeugung innerhalb der Unit-Tests wegmocken und dort fest definierte, immer selbe GUIDs zurückgeben.

beste Grüße
zommi
private Nachricht | Beiträge des Benutzers
spike24
myCSharp.de - Member



Dabei seit:
Beiträge: 451
Herkunft: Steiermark Österreich

Themenstarter:

beantworten | zitieren | melden

@gfoidl
Ja, ich denke Du hast mich richtig verstanden, allerdings probiere ich schon ewig damit herum und schaffe es nicht um die Burg.
Die Haltepunkte die ich da setzte werden nicht mal angesprungen. Also wenn etwas falsches geliefert werden würde wäre es ja noch ok, aber es wird nicht mal was aufgerufen.

Hier ein OriginalCode (nicht aufbereitet) der den Callback nicht aufruft:

mObjectStoreServerMock.Setup(mock => mock.ProcessModification(
It.IsAny<ProcessModificationArgument>()))
.Callback<ProcessModificationArgument>(argument => EqualsProcessModificationArgument(argument, processModificationEventArgs)
).Returns(TestResults.LoadProcessModificationResult(processModificationEventArgs));

@zoomi
war ein Fehler im Aufbereiten, habs schon ausgebessert.

Generell wollte ich sowas vermeiden, nur wegen dem Testen ein neues Interface einführen. (Oder ProcessIdentifierFactory (liefert die Guid))
Vorallem da das Ding das fast public sein müsste damit ich auch von den Tests darauf zugreifen müsste. Und das schmeckt mir dann garnicht.
mbg
Rossegger Robert
mehr fragen mehr wissen

Montag morgen ist die beste Zeit um eine erfolgreiche Woche zu beginnen
private Nachricht | Beiträge des Benutzers
gfoidl
myCSharp.de - Team

Avatar #avatar-2894.jpg


Dabei seit:
Beiträge: 7563
Herkunft: Waidring

beantworten | zitieren | melden

Hallo spike24,
Zitat
Generell wollte ich sowas vermeiden, nur wegen dem Testen ein neues Interface einführen.
Das ist aber in der Regel gutes Design :-)

Zum Problem: so wie das Setup ist wird das Return "eager" ausgeführt, also sofort beim Initialisieren und danach nciht mehr. Wenn du es "lazy" machts sollte es passen.


.Returns(() => ....);


mfG Gü
Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"
private Nachricht | Beiträge des Benutzers
spike24
myCSharp.de - Member



Dabei seit:
Beiträge: 451
Herkunft: Steiermark Österreich

Themenstarter:

beantworten | zitieren | melden

Ich hab das Retrun umgebaut, jetzt wird sie garnicht mehr aufgerufen !?!
Finde ich jetzt aber auch schräg.
Generell hatte ich aber das Problem dass EqualsProcessModificationArgument nicht aufgerufen wird.

Ist ein gutes Design, einen privat Spass einer Klasse auslagern nur zum testen?
Hmm widerstrebt mir irgendwie, vorallem da es ja zum Mocken gehen sollte

// EDIT:
gerade gefunden in Moq.Mock<T> - how to setup a method that takes an expression:
Zitat
However you are coming up against one of Moq's shortcomings. You would want to put an actual expression there instead of using It.IsAny, but Moq doesn't support setting up methods that take expressions with specific expressions (it's a difficult feature to implement). The difficulty comes from having to figure out whether two expressions are equivalent.

Heist das, das geht nicht?
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von spike24 am .
mbg
Rossegger Robert
mehr fragen mehr wissen

Montag morgen ist die beste Zeit um eine erfolgreiche Woche zu beginnen
private Nachricht | Beiträge des Benutzers
Ahrimaan
myCSharp.de - Member



Dabei seit:
Beiträge: 363
Herkunft: Thorn

beantworten | zitieren | melden

Es ist immer gutes Design gegen Interfaces zu programmieren ;-)
private Nachricht | Beiträge des Benutzers
gfoidl
myCSharp.de - Team

Avatar #avatar-2894.jpg


Dabei seit:
Beiträge: 7563
Herkunft: Waidring

beantworten | zitieren | melden

Hallo spike24,

wenn der Mock richtig konfiguriert wird und es trotzdem nicht aufgerufen wird dann wird es wahrscheinlich von der Methode die zu testen ist nicht aufgerufen. Prüfe dort mal.
Zitat
Ist ein gutes Design, einen privat Spass einer Klasse auslagern nur zum testen?
Da es nicht das Thema ist nur kurz: Kommt darauf an ;-)
Wenn damit Single-Reponsibility erreicht wird ja. Beispiel:


public interface IGuidGenerator {...}

public class DortWoEsVerwendetWerdenSoll
{
    private readonly IGuidGenerator _guidGenerator;

    public DortWoEsVerwendetWerdenSoll(IGuidGenerator guidGenerator)
    {
        _guidGenerator = guidGenerator;
    }
}
So kann der GuidGenerator extra getestet werden und auch die Klasse DortWoEsVerwendetWerdenSoll indem IGuidGenerator gemockt wird.
Sonst kann privates (das eindeutig zur Funktionalität der Klasse gehört) auch über die public Member getestet werden. Wenn es nicht dazu gehört gehört es auch in eine eigene Klasse.

Für weitere Infos darüber suche im Forum, das wurde schon einige male besprochen.


mfG Gü
Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"
private Nachricht | Beiträge des Benutzers
Sarc
myCSharp.de - Member



Dabei seit:
Beiträge: 426

beantworten | zitieren | melden

Hallo,

prüf doch erstmal, ob der Aufurf überhaupt stattfindet.

mTestClassMock.Setup(mock => mock.MethodToTest(It.IsAny<ProcessArgument>())).Returns(bla);
...

mTestClassMock.VerifyAll();
private Nachricht | Beiträge des Benutzers
spike24
myCSharp.de - Member



Dabei seit:
Beiträge: 451
Herkunft: Steiermark Österreich

Themenstarter:

beantworten | zitieren | melden

@Ahrimaan
Alleine wenn jemand bei Patterns 'immer' sagt stelle ich es in Frage.
Es ist richtig gegen interfaces zu programmieren hat definitv einen Sinn, allerdings kenne ich auch das Gegenteil. Bei uns in der Firma programmieren wir gegen soviele Interfaces (weil dann können wir alles austauschen und customizen) dass sich keiner mehr auskennt was eigentlich abgeht und das erste Interface, bzw die Klasse dazu sieht noch immer gleich aus wie vor drei Jahren wie ich es programmiert habe, also nix mit austauschen. Und einen haben wir, der implementier ein Interface wenn es techniss einen Sinn ergibt, und ich kann Dir sagen niemand versteht seinen Code.

@gfoidl
Das SRP ist mir im Grund klar und ich gehe auch darauf ein wenn ich etwas entwickle. Allerdings mache ich in diesem Bereich wegen der Lesbarkeit und wartbarkeit Abstriche. eine ProcessModificationIdentifier hinter einem Interface mit IOC und DI bereitstellen ist schwieriger zu entziffern als
ProcessModificationIdentifier identifier = new ProcessModiificationIdentifier();
(da drin ist die Guid), ein klick go to definition und ich sehe die Klasse, sonst muss ich das interface suche und dann kucken wer das alles implementiert.
Ich verstehe das Prinzip, aber wenn es das Verständnis des Codes erschwert gehe ich gerne Kompromisse ein.

Und an Dich geht auch die Medailie fürs helfen, und ich bekomme wiedereinmal die Goldene Ananas. Offensichtlich habe ich beim herumprobieren in den letzten 3 Wochen irgendwas kaputt gemacht, jetzt habe ich es nun gerichtet. Jetzt kommt was falsches aber es wird wenigstens aufgerufen.

@Sarc
Du hast auch in die richtige Kerbe geschlagen.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von spike24 am .
mbg
Rossegger Robert
mehr fragen mehr wissen

Montag morgen ist die beste Zeit um eine erfolgreiche Woche zu beginnen
private Nachricht | Beiträge des Benutzers