Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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()
{
    // 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();
}
like image 200
Russell Giddings Avatar asked Dec 31 '25 00:12

Russell Giddings


2 Answers

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();
like image 126
Jeff Sternal Avatar answered Jan 01 '26 12:01

Jeff Sternal


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.

like image 34
Mark Seemann Avatar answered Jan 01 '26 12:01

Mark Seemann