I am using NPoco that comes with IDatabase class for the database call methods. I want to verify that the object going into the NPoco Insert method has the correct data(in the form of a domain object).

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

The code being called(what should trigger the verify)

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

}
有帮助吗?

解决方案

The code in your SUT uses an IUnitOfWorkProvider to produce the IUnitOfWork:

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

The IUnitOfWork instances that you are currently trying to mock are some other instances. They aren't produced by this IUnitOfWorkProvider.

Assuming that the IUnitOfWorkProvider is injected into your SUT, you should be able to Freeze that and go from there. Something like this ought to work:

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...

其他提示

you need to make your mocked calls verifiable

unitOfWork
    .Setup(x => x.Db.Insert(It.IsAny<MyDomainObject>()))
    .Verifiable();
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top