Entwickler-Ecke

Sonstiges (.NET) - NUnit und Moq, Verständnisfrage zu einem gemockten Interface


karstenK - Fr 15.11.13 13:05
Titel: NUnit und Moq, Verständnisfrage zu einem gemockten Interface
Hallo Community,

ich habe angefangen mich mit Unit-Tests zu beschäftigen. Dabei bin ich auf das Thema Mocken gestoßen. Und fand es sehr interessant das man ein Interface mocken kann ohne das man eine Implementation davon benötig.

Ich habe mal ein kleines Beispiel erstellt:

ITrackingRule


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
  public interface ITrackingRule{
    string Domain{
      get;
    }

    string Name{
      get;
    }

    string LinkPathWithoutDomain{
      get;
    }

    IMediaItem LastMediaItem{
      get;
      set;
    }
  }



Dafür habe ich einen Test erstellt mithilfe von Moq. IMediaItem ist ein weiteres Interface was ich benutze, es speichert auch nur ein paar Werte.

TrackingRuleTests


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
class TrackingRuleTests {
    private string _domain;
    private string _name;
    private string _linkpathwithoutdomain;
    private MockRepository _mockRepository;
    private Mock<ITrackingRule> _mockedTrackingRule;
    private Mock<IMediaItem> _mockedMediaItem;
    
    [SetUp]
    public void SetUp() {
      _domain = "domain";
      _name = "name";
      _linkpathwithoutdomain = "linkPathWithoutDomain";

      _mockRepository = new MockRepository(MockBehavior.Strict);
      _mockedTrackingRule = _mockRepository.Create<ITrackingRule>();
      _mockedMediaItem = _mockRepository.Create<IMediaItem>();
    }

    [Test]
    public void HasDomain(){
      _mockedTrackingRule.SetupGet(trackingRule => trackingRule.Domain).Returns(_domain);
      Assert.That(_mockedTrackingRule.Object.Domain, Is.EqualTo(_domain));
    }

    [Test]
    public void HasName(){
      _mockedTrackingRule.SetupGet(trackingRule => trackingRule.Name).Returns(_name);
      Assert.That(_mockedTrackingRule.Object.Name, Is.EqualTo(_name));
    }

    [Test]
    public void HasLinkPathWithoutDomain(){
      _mockedTrackingRule.SetupGet(trackingRule => trackingRule.LinkPathWithoutDomain).Returns(_linkpathwithoutdomain);
      Assert.That(_mockedTrackingRule.Object.LinkPathWithoutDomain, Is.EqualTo(_linkpathwithoutdomain));
    }

    [Test]
    public void LastMediaItemIsNullAfterInitialization(){
      _mockedTrackingRule.SetupGet(trackingRule => trackingRule.LastMediaItem).Returns((IMediaItem)null);
      Assert.That(_mockedTrackingRule.Object.LastMediaItem, Is.Null);
    }

    [Test]
    public void LastMediaItemIsNotNullAfterUpdate(){
      _mockedTrackingRule.SetupGet(trackingRule => trackingRule.LastMediaItem).Returns(_mockedMediaItem.Object);
      Assert.That(_mockedTrackingRule.Object.LastMediaItem, Is.EqualTo(_mockedMediaItem.Object));
    }
  }


Nun habe ich die Klasse TrackingRule erstellt, welche das Interface ITrackingRule implementiert.

TrackingRule


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
public class TrackingRule:ITrackingRule{
    public TrackingRule(string domain, string name, string linkpathwithoutdomain){
      Domain = domain;
      Name = name;
      LinkPathWithoutDomain = linkpathwithoutdomain;
    }

    #region Implementation of ITrackingRule

    public string Domain{
      get;
      private set;
    }

    public string Name{
      get;
      private set;
    }

    public string LinkPathWithoutDomain{
      get;
      private set;
    }

    public IMediaItem LastMediaItem{
      get;
      set;
    }

    #endregion
  }


Jetzt würde ich gerne wissen, was mir das Mocken von dem Interface gebracht hat, da ich ja jetzt die Implementation trotzdem prüfen muss. Kann ich irgendwas davon wieder verwenden, um die Implementation zu testen? oder muss ich alle Test erneut nur mit dem konkreten Typ testen?

Gruß
Karsten

Moderiert von user profile iconTh69: Beitragsformatierung überarbeitet: Size von 18 auf 14 verkleinert


Ralf Jansen - Fr 15.11.13 13:22

Alle Klassen die du testen möchtest und eine Abhängigkeit auf ITrackingRule haben kannst du mit dem Moq auf ITrackingRule versorgen. Es geht ja immer darum möglichst ein einzelnes Ding zu testen und nicht auch noch die Abhängigkeiten. Heißt du schreibst Test für TrackingRule in dem du die Abhängigkeiten von TrackingRule durch Mocks ersetzt um nur TrackingRule zu testen. Und genauso gehst du beim Test jeder anderen Klasse vor . Du Mocks die konkreten Abhängigkeiten weg um jeweils nur die einzelne Klasse zu testen.

Ich habe nicht genau angeschaut was du gemacht hast aber wenn du den Mock testest wäre das sicher sinnfrei.