2010-02-22 55 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