4

我正在为数据库调用方法使用 IDatabase 类附带的 NPoco。我想验证进入 NPoco Insert 方法的对象是否具有正确的数据(以域对象的形式)。

   public interface IUnitOfWorkProvider
    {
        IUnitOfWork GetUnitOfWork();
    }

    public interface IUnitOfWork : IDisposable 
        {
            void Commit();
            IDatabase Db { get; }
            void SetOneTimeCommandTimeout(int timeout);
            void SetGlobalCommandTimeout(int timeout);
        }
    public interface IDatabase : IDatabaseQuery
    {
        IDbConnection Connection { get; }
        IDbTransaction Transaction { get; }

        void AbortTransaction();
        void BeginTransaction();
        void BeginTransaction(IsolationLevel? isolationLevel);
        void CompleteTransaction();
        IDataParameter CreateParameter();
        int Delete(object poco);
        int Delete<T>(object pocoOrPrimaryKey);
        int Delete<T>(Sql sql);
        int Delete<T>(string sql, params object[] args);
        int Delete(string tableName, string primaryKeyName, object poco);
        int Delete(string tableName, string primaryKeyName, object poco, object primaryKeyValue);
        void Dispose();
        Transaction GetTransaction();
        Transaction GetTransaction(IsolationLevel? isolationLevel);
        object Insert(object poco);
        object Insert(string tableName, string primaryKeyName, object poco);
        object Insert(string tableName, string primaryKeyName, bool autoIncrement, object poco);
        void Save(object poco);
        void Save(string tableName, string primaryKeyName, object poco);
        IDatabase SetTransaction(IDbTransaction tran);
        int Update(object poco);
        int Update<T>(Sql sql);
        int Update(object poco, IEnumerable<string> columns);
        int Update(object poco, object primaryKeyValue);
        int Update<T>(string sql, params object[] args);
        int Update(object poco, object primaryKeyValue, IEnumerable<string> columns);
        int Update(string tableName, string primaryKeyName, object poco);
        int Update(string tableName, string primaryKeyName, object poco, IEnumerable<string> columns);
        int Update(string tableName, string primaryKeyName, object poco, object primaryKeyValue);
        int Update(string tableName, string primaryKeyName, object poco, object primaryKeyValue, IEnumerable<string> columns);
    }

 // my test class file
 private IFixture fixture;
  private Mock<IUnitOfWork> unitOfWork;
  private MyService myService;
     private Mock<IDatabase> database; // new based on responses

    [SetUp]
        public void Setup()
        {
            fixture = new Fixture().Customize(new AutoMoqCustomization());
 database = fixture.Freeze<Mock<IDatabase>>();// new based on responses 
            unitOfWork = fixture.Freeze<Mock<IUnitOfWork>>();
            myService = fixture.CreateAnonymous<MyService>();
        }

        [Test]
        public MyTest()
        {       
              // fails
            unitOfWork.Setup(x => x.Db.Insert(It.IsAny<MyDomainObject>()));
            myService.CallMyMethod();
            unitOfWork.Verify(x => x.Db.Insert(It.IsAny<MyDomainObject>()));

            // fails
            unitOfWork.Setup(x => x.Db.Insert(It.IsAny<object>()));
            myService.CallMyMethod();
            unitOfWork.Verify(x => x.Db.Insert(It.IsAny<object>()));
// fails (this was a try based on responses)
 database.Setup(x => x.Insert(It.IsAny<object>()));       
 myService.CallMyMethod();        
 database.Verify(x => x.Insert(It.IsAny<object>()));

            // passes
            unitOfWork.Setup(x => x.Db.Insert(It.IsAny<object>()));
            myService.CallMyMethod();
            unitOfWork.Verify();
        }

public class MyDomainObject
{
   public void Id {get; set;}
}

被调用的代码(什么应该触发验证)

 using (var unitOfWork = unitOfWorkProvider.GetUnitOfWork())
            {
       MyDomainObject myDomain = anotherService.getMyDomain(DateTime.Now, 100);
       unitOfWork.Db.Insert(myDomain); 

}
4

2 回答 2

2

SUT中的代码使用 IUnitOfWorkProvider 来生成 IUnitOfWork:

using (var unitOfWork = unitOfWorkProvider.GetUnitOfWork())
{
    MyDomainObject myDomain = anotherService.getMyDomain(DateTime.Now, 100);
    unitOfWork.Db.Insert(myDomain); 
}

您当前尝试模拟的 IUnitOfWork 实例是其他一些实例。它们不是由这个 IUnitOfWorkProvider 生成的。

假设 IUnitOfWorkProvider 被注入到您的 SUT 中,您应该能够冻结它并从那里开始。像这样的东西应该可以工作:

var fixture = new Fixture().Customize(new AutoMoqCustomization());
var uowProviderStub = fixture.Freeze<Mock<IUnitOfWorkProvider>>();
var uowMock = fixture.CreateAnonymous<Mock<IUnitOfWork>>();
var sut = fixture.CreateAnonymous<MyService>();

uowProviderStub.Setup(p => p.GetUnitOfWork()).Returns(uowMock.Object);
uowMock
    .Setup(x => x.Db.Insert(It.IsAny<MyDomainObject>()))
    .Verifiable();

// etc.

That's all a bit of a bother, which is really the test trying to tell you that the Law of Demeter violation is not the best of designs...

于 2012-11-01T05:03:51.913 回答
0

你需要让你的模拟调用可验证

unitOfWork
    .Setup(x => x.Db.Insert(It.IsAny<MyDomainObject>()))
    .Verifiable();
于 2012-10-31T22:10:31.107 回答