Question

I have a method that adds an object to a database, processes that object, and then updates the same object in the database if the processing was successful. The processing is a very critical part of the system (payment) so I want to make sure that if the system crashes/power cut during the processing, we still have the initial add that we can then process again.

public void CreateAndProcess(){
        var myObj= new myObj
        {
            // Set up myObj here
        };

        db.Add(myObj);
        db.SaveChanges();

        // Process and update myObj here

        db.Update(myObj);
        db.SaveChanges();
}

I then want to unit test the CreateAndProcess method to ensure that the Add and Update methods were called with myObj containing the correct values.

// addedObj and updatedObj are objects I define in my test that should match.    
_store.AssertWasCalled(store => store.Add(Arg<myObj>.Matches(mo => Equal(mo, addedObj))), 
                       option => option.Repeat.Once()); // Initial add to db
_store.AssertWasCalled(store => store.Update(Arg<myObj>.Matches(mo => Equal(mo, updatedObj))), 
                       option => option.Repeat.Once()); // Update in db after processed

private static bool Equal(myObj s1, myObj s2)
{
   // Used to match a subset of properties I care about
   Assert.That(s1.myProp, Is.EqualTo(s2.myProp), "Unexpected argument");
   return true;
}

The issue is that the first AssertWasCalled is using the final state of the object, after it is updated, rather than it's value at the time the Add() function was called.

How can I test the state of myObj at the time it was initially added to the database?

Thanks,

Était-ce utile?

La solution

Rhino Mock provides Do() handler to access stubbed methods arguments at the time when stubbed method is called.
So, it is possible to write a custom handler for Add(MyObj) method which can store the necessary fields of myObj argument passed. And then it is possible to run asserts against stored fields.

Here is an example:

string actualMyPropOnAdd = null;

_store
    .Stub(s => s.Add(Arg<MyObj>.Is.Anything))
    .Do((Action<MyObj>)(myObj =>
    {
        // save the necessary properties to validate them later
        actualMyPropOnAdd = myObj.myProp;
    }));

// call CreateAndProcess() here

// validate saved properties:
Assert.That(actualMyPropOnAdd, Is.EqualTo(expectedMyPropOnAdd));

Also I'd recommend to follow one asser per test rule and to write another separate test to validate that argument passed to Update() method is correct.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top