简体   繁体   English

如何在Moq中调试验证?

[英]How to debug verify in moq?

I am using NPoco that comes with IDatabase class for the database call methods. 我正在使用IDatabase类随附的NPoco作为数据库调用方法。 I want to verify that the object going into the NPoco Insert method has the correct data(in the form of a domain object). 我想验证进入NPoco插入方法的对象是否具有正确的数据(以域对象的形式)。

   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: SUT中的代码使用IUnitOfWorkProvider生成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. 您当前尝试模拟的IUnitOfWork实例是其他一些实例。 They aren't produced by this IUnitOfWorkProvider. 它们不是由此IUnitOfWorkProvider生成的。

Assuming that the IUnitOfWorkProvider is injected into your SUT, you should be able to Freeze that and go from there. 假设将IUnitOfWorkProvider注入到您的SUT中,您应该可以冻结它并从那里进行操作。 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... 这有点麻烦,这实际上是一项测试,试图告诉您违反Demeter法则并非最佳设计...

you need to make your mocked calls verifiable 您需要使您的模拟通话可验证

unitOfWork
    .Setup(x => x.Db.Insert(It.IsAny<MyDomainObject>()))
    .Verifiable();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM