1

MVC コントローラーをテストできるように、コードをモックするのに実際に問題があります。

私のリポジトリは次のインターフェースを実装しています

public interface IEntityRepository<T>
{
    IQueryable<T> All { get; }
    IQueryable<T> AllIncluding(params Expression<Func<T, object>>[] includeProperties);
    void Delete(int id);
    T Find(int id);
    void InsertOrUpdate(T entity);
    void InsertOrUpdateGraph(T entity);
}

そのようです

public interface IMonkeyRepository : IEntityRepository<Monkey>
{
}

私のEFコンテキストは、次のインターフェースを実装しています

public interface IMonkeyContext
{
    IDbSet<Monkey> Monkeys { get; set; }
    DbEntityEntry Entry(object entity);
    IEnumerable<DbEntityValidationResult> GetValidationErrors();
    int SaveChanges();
}

私の作業単位インターフェースはそのように定義されています

public interface IUnitOfWork<TContext> : IDisposable
{
    TContext Context { get; }
    int Save();
} 

そして実装

public class MonkeyUnitOfWork : IUnitOfWork<IMonkeyContext>
{

    private readonly IMonkeyContext context;
    private bool disposed;
    public MonkeyUnitOfWork(IMonkeyContext context)
    {
        this.context = context;
    }
    public IMonkeyContext Context
    {
        get
        {
            return this.context;
        }
    }
    public void Dispose()
    {
        this.Dispose(true);
        GC.SuppressFinalize(this);
    }

    public int Save()
    {
        var ret = this.context.SaveChanges();
        return ret;
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (disposing)
            {
                ((DbContext)this.context).Dispose();
            }
        }

        this.disposed = true;
    }
}

テストしたい Create アクションの MonkeyController があります。私は定義されています

        if (this.ModelState.IsValid)
        {
            this.repo.InsertOrUpdate(Mapper.Map<MonkeyModel, Monkey>(monkey));
            this.uow.Save();
            return this.RedirectToAction(MVC.Monkey.Index());
        }

        return this.View(monkey);

私の単体テストでは、RhinoMocks を使用しており、テストを定義しています。

[TestFixture]
public class MonkeyControllerTests
{
    MockRepository mocks = null;

    private IMonkeyRepository monkeyRepository;

    private IMonkeyContext context;

    private MonkeyUnitOfWork unitOfWork;       

    private MonkeyController controller;

    [SetUp]
    public virtual void SetUp()
    {
        TestHelpers.SetupAutoMap();

        this.monkeyRepository = this.Mocks.StrictMultiMock<IMonkeyRepository>(typeof(IEntityRepository<Monkey>));

        this.context = this.Mocks.StrictMock<IMonkeyContext>();

        this.unitOfWork = new MonkeyUnitOfWork(this.context);

        this.controller = new MonkeyController(this.MonkeyRepository, this.unitOfWork);
    }

    [TearDown]
    public virtual void TearDown()
    {
        if (this.mocks != null)
        {
            try
            {
                this.mocks.ReplayAll();
                this.mocks.VerifyAll();
            }
            finally
            {
                this.mocks = null;
            }
        }
    }

    public MockRepository Mocks
    {
        get
        {
            if (mocks == null)
                mocks = new MockRepository();
            return mocks;
        }
    }

    [Test]
    public void MonkeyCreateShouldShouldDoSomeStuff()
    {
        var monkeyModel = ViewModelTestHelpers.CreateSingleMonkey();
        var monkey = Mapper.Map<MonkeyModel, Monkey>(monkeyModel);

        this.monkeyRepository.Expect(action => action.InsertOrUpdate(monkey));

        this.context.Expect(action => action.SaveChanges()).Return(1);
        var result = (RedirectToRouteResult)this.controller.Create(monkeyModel);

        Assert.AreEqual(MVC.Monnkey.ActionNames.Index, result.RouteValues["action"]);
    }
}

テストを実行すると、次のエラーが発生します

前のメソッド「IMonkeyContext.SaveChanges();」戻り値またはスローする例外が必要です。

または、IEntityRepository.InsertOrUpdate が 1 実際の 0 を期待していると不平を言います

これを機能させるために非常に多くのキャストと呪文を試しましたが、困惑しています。これらのオブジェクトを正しくモックする方法を知っている人はいますか? または、ここで根本的に何かを見逃した場合は?

4

1 に答える 1

1

まあ、それは男子生徒のエラーのようです

IEntityRepository.InsertOrUpdate が呼び出されていないというのは、RhinoMocks が正しかったということです。

テストでビューモデルからモデルにマップするコード行

var monkey = Mapper.Map<MonkeyModel, Monkey>(monkeyModel);

そしてそれをexpectで使用します

this.monkeyRepository.Expect(action => action.InsertOrUpdate(monkey));

もちろん、関数はこの正確なサルのインスタンスで呼び出す必要があることをRhinoに伝えていました。

もちろん、関数はアクション内で次の方法で呼び出されます

this.repo.InsertOrUpdate(Mapper.Map<MonkeyModel, Monkey>(monkey));

同じインスタンスではありません。

現在、aaa 構文に移行し、テスト コードを次のように変更しました。

this.monkeyRepository.Stub(r => r.InsertOrUpdate(Arg<Monkey>.Is.Anything));

と主張する

this.monkeyRepository.AssertWasCalled(r => r.InsertOrUpdate(Arg<Monkey>.Is.Anything));

私は今行き、恥をかいて頭を垂れます。

于 2012-12-05T10:50:06.200 に答える