2010-02-22 60 views
3

我有一個方法,調用一個服務來檢索一個對象的實例,更新實例,然後將實例保存回服務(代碼如下)。在模擬檢查更新的實例

我想知道的是,如果在起訂量一個很好的方法來檢查以下內容: -

  1. 也正在被保存回服務實例的原始實例
  2. 的修改版
  3. 該實例已更新爲所需

我知道我可以使用It.Is<MyThing>(x => x.Name == newName)檢查這裏點2。儘管如此,忽略了第1點。

有沒有一種乾淨的方式來實現這一目標?

類代碼:

public class MyClass 
{ 
    private readonly IThingService thingService; 

    public MyClass(IThingService thingService) 
    { 
     this.thingService = thingService; 
    } 

    public void SaveMyThing(MyThing myThing) 
    { 
     var existingThing = thingService.Get(myThing.Id); 
     existingThing.Name = myThing.Name; 
     thingService.Save(existingThing); 
    } 
} 

public class MyThing 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
} 

public interface IThingService 
{ 
    MyThing Get(int id); 
    void Save(MyThing myThing); 
} 

TEST CODE:

[Test] 
public void Save_NewName_UpdatedThingIsSavedToService() 
{ 
    // Arrange 
    var myThing = new MyThing { 
           Id = 42, 
           Name = "Thing1" 
          }; 
    var thingFromService = new MyThing 
        { 
         Id = 42, 
         Name = "Thing2" 
        }; 

    var thingService = new Mock<IThingService>(); 
    thingService 
     .Setup(ts => ts.Get(myThing.Id)) 
     .Returns(thingFromService); 
    thingService 
     .Setup(ts => ts.Save(**UPDATED-THING-FROM-SERVICE**)) 
     .Verifiable(); 

    var myClass = new MyClass(thingService.Object); 

    // Act 
    myClass.SaveMyThing(myThing); 

    // Assert 
    thingService.Verify(); 
} 

回答

1

如果我理解正確,您想驗證傳遞給ts.Save的參數是否是從服務返回的實例。

如果這是真的,除了檢查參考平等覈實該Name值滿足您的期望:

thingService 
    .Setup(ts => ts.Save(It.Is<MyThing>(thing => thing == thingFromService 
               && thing.Name = myThing.Name)) 
    .Verifiable(); 
+0

太棒了!我期望「thing == thingFromService」返回false爲「thing.Name!= thingFromService.Name」。事實並非如此,因爲thingFromService是在測試方法中更新的對象,因此是相同的。這是漫長的一天;-)謝謝傑夫! – 2010-02-22 18:28:26

1

你幾乎有:

[Test] 
public void Save_NewName_UpdatedThingIsSavedToService() 
{ 
    // Arrange 
    var myThing = new MyThing { 
           Id = 42, 
           Name = "Thing1" 
          }; 
    var thingFromService = new MyThing 
        { 
         Id = 42, 
         Name = "Thing2" 
        }; 

    var thingService = new Mock<IThingService>(); 
    thingService 
     .Setup(ts => ts.Get(myThing.Id)) 
     .Returns(thingFromService) 
     .Verifiable(); 
    thingService 
     .Setup(ts => ts.Save(It.Is<MyThing>(x => x.Name == myThing.Name))) 
     .Verifiable(); 

    var myClass = new MyClass(thingService.Object); 

    // Act 
    myClass.SaveMyThing(myThing); 

    // Assert 
    thingService.Verify(); 
} 

的主要區別是,我還添加了調用Verifiable()到第一次安裝,然後我添加了It.Is檢查你已經提到的喲你的回答。由於謂詞,只有當謂詞計算結果爲真時纔會匹配Save方法,在這種情況下Verify調用成功。

但是,這個測試實際測試了兩件事(Get和Save)。爲避免Assertion Roulette,最好將它分成兩個測試。

+0

是的,我明白這一點。有效地,對thingService的「Get」調用是一個存根(而不是模擬),因此它不需要.Verify()。 該代碼的問題在於,它不會區分將「thingFromService」實例的更新版本傳遞給Save方法,而只是將傳入MyThing實例傳遞給SaveMyThing方法(我的問題中的第1點)。 :-( – 2010-02-22 17:58:45

0

我同意馬克的回答,但有點貴先聲明混淆。您是否試圖找出對象是否爲相同的對象引用或對象類型? It.Is只是確保參數是MyThing的類型,而不是它實際參考您的上一個對象。

如果你想攔截的價值傳遞給你的模擬服務比你可以使用一個回調像下面,然後做你想要的任何斷言結果對象:

MyThing result = null; 

thingService 
    .Setup(ts => ts.Save(It.Is<MyThing>(x => x.Name == myThing.Name))) 
    .Callback((MyThing saved) => result = saved) 
    .Verifiable(); 
+0

我想檢查它是具有更新屬性的同一個對象引用 – 2010-02-22 18:00:30