开发者

Check For Updated Instance in Mock

I have a method that calls a service to retrieve an instance of an object, updates the instance then saves the instance back to the service (the code for this is below).

What I want to know is if there is a nice way in Moq to check the following:-

  1. That the instance that is being saved back to the service is a modified version of the original instance
  2. That the instance has been updated as desired

I know I can use It.Is<MyThing>(x => x.Name == newName) to check for point 2 here. Doing this ignores point 1 though.

Is there a clean way to achieve this?

CLASS CODE:

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()
{
    // Arra开发者_如何学Cnge
    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();
}


If I understand correctly, you want to verify that the parameter passed to ts.Save is the instance returned from the service.

If that's true, check reference equality in addition to verifying that the Name value meets your expectations:

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


You are almost there:

[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();
}

The main difference is that I also added a call to Verifiable() to the first Setup, and then I added the It.Is check you already mentioned in your answer. Because of the predicate, the Save method will only be matched when the predicate evaluates to true, in which case the Verify call succeeds.

However, this test actually tests two things (Get and Save). To avoid Assertion Roulette, it would be better to split it up into two tests.


I agree with Mark's answer but a bit confused by your first statement. Are you trying to find out if the object is the same object reference or object type? The It.Is just makes sure that parameter is the type of MyThing, not that it is the actual reference to your previous object.

If you want to intercept the value being passed to your mock service than you could use a callback like below and then do whatever assertions you want on the result object:

MyThing result = null;

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜