RhinoMock AssertWasCalled对同一个对象调用两次

本文关键字:两次 调用 AssertWasCalled 一个对象 RhinoMock | 更新日期: 2023-09-27 18:02:37

我有一个方法,它将对象添加到数据库中,处理该对象,然后在处理成功时更新数据库中的同一对象。处理是系统(支付)中非常关键的一部分,所以我想确保如果系统在处理过程中崩溃/停电,我们仍然有初始添加,然后我们可以再次处理。

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

然后我想对CreateAndProcess方法进行单元测试,以确保使用包含正确值的myObj调用Add和Update方法。

// 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;
}

问题是第一个AssertWasCalled使用对象的最终状态,在它被更新之后,而不是它在Add()函数被调用时的值。

如何测试myObj在最初添加到数据库时的状态?

谢谢,

RhinoMock AssertWasCalled对同一个对象调用两次

Rhino Mock提供Do()处理程序,以便在调用存根方法时访问存根方法的参数。
因此,可以为Add(MyObj)方法编写一个自定义处理程序,该处理程序可以存储传递的myObj参数的必要字段。然后可以对存储的字段运行断言。

下面是一个例子:

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));

我还建议每个测试规则遵循一个asser,并编写另一个单独的测试来验证传递给Update()方法的参数是正确的。