エンティティフレームワーク(コードファーストアプローチ)を使用したN層アプリケーションがあります。今私はいくつかのテストを自動化したいと思います。私はMoqフレームワークを使用しています。私はテストを書くことについていくつかの問題を発見しています。おそらく私の建築は間違っているでしょうか?間違っていると、私はよく分離されていないコンポーネントを書いているので、テスト可能ではありません。私は本当にこれが好きではない...またはおそらく、私は単にmoqフレームワークを正しく使用することはできません。エンティティフレームワークをN層アーキテクチャでモックする方法
私はあなたが私のアーキテクチャを見てみましょう:私はクラスのコンストラクタで、私のcontext
を注入あらゆるレベルで
を。
外観:
public class PublicAreaFacade : IPublicAreaFacade, IDisposable
{
private UnitOfWork _unitOfWork;
public PublicAreaFacade(IDataContext context)
{
_unitOfWork = new UnitOfWork(context);
}
}
BLL:
public abstract class BaseManager
{
protected IDataContext Context;
public BaseManager(IDataContext context)
{
this.Context = context;
}
}
レポジトリ:
public class Repository<TEntity>
where TEntity : class
{
internal PublicAreaContext _context;
internal DbSet<TEntity> _dbSet;
public Repository(IDataContext context)
{
this._context = context as PublicAreaContext;
}
}
IDataContext
私DbContextによって実装されるインターフェースである。
public partial class PublicAreaContext : DbContext, IDataContext
さて、私はEF
を模擬し、どのように私はテストを書く方法:
[TestInitialize]
public void Init()
{
this._mockContext = ContextHelper.CreateCompleteContext();
}
ContextHelper.CreateCompleteContext()
は次のとおりです。
public static PublicAreaContext CreateCompleteContext()
{
//Here I mock my context
var mockContext = new Mock<PublicAreaContext>();
//Here I mock my entities
List<Customer> customers = new List<Customer>()
{
new Customer() { Code = "123455" }, //Customer with no invoice
new Customer() { Code = "123456" }
};
var mockSetCustomer = ContextHelper.SetList(customers);
mockContext.Setup(m => m.Set<Customer>()).Returns(mockSetCustomer);
...
return mockContext.Object;
}
そして、ここで私は私のテストを書く方法:
[TestMethod]
public void Success()
{
#region Arrange
PrepareEasyPayPaymentRequest request = new PrepareEasyPayPaymentRequest();
request.CodiceEasyPay = "128855248542874445877";
request.Servizio = "MyService";
#endregion
#region Act
PublicAreaFacade facade = new PublicAreaFacade(this._mockContext);
PrepareEasyPayPaymentResponse response = facade.PrepareEasyPayPayment(request);
#endregion
#region Assert
Assert.IsTrue(response.Result == it.MC.WebApi.Models.ResponseDTO.ResponseResult.Success);
#endregion
}
ここでは、それはすべて正常に動作するようです!そして私の建築が正しいように見えます。しかし、エンティティを挿入/更新したいのですが?もう何も働かない!私は理由を説明:
あなたが見ることができるように、私はその後、私のTOAに、私はDTOのpropertiessから私のエンティティを生成、ファサードに(それはDTOです)*Request
オブジェクトを渡す:
private PaymentAttemptTrace CreatePaymentAttemptTraceEntity(string customerCode, int idInvoice, DateTime paymentDate)
{
PaymentAttemptTrace trace = new PaymentAttemptTrace();
trace.customerCode = customerCode;
trace.InvoiceId = idInvoice;
trace.PaymentDate = paymentDate;
return trace;
}
PaymentAttemptTrace
Entity Frameworkに挿入するエンティティです。これは嘲笑されず、挿入できません。したがって、私の虚偽のコンテキスト(IDataContext)を渡しても、私のテストが失敗したエンティティを挿入しようとすると、私のテストは失敗します!
ここで私は間違ったアーキテクチャを持っている疑いがある!
どうしたの?アーキテクチャまたは私がmoqを使う方法は?
は、ここで私は自分のコードをテストする方法の助けを
UPDATE
をいただき、ありがとうございます...例えば、私は支払いのトレースをテストしたいです。..ここで
テスト:ここ
[TestMethod]
public void NoPaymentDate()
{
TracePaymentAttemptRequest request = new TracePaymentAttemptRequest();
request.AliasTerminale = "MyTerminal";
//...
//I create my request object
//You can see how I create _mockContext above
PublicAreaFacade facade = new PublicAreaFacade(this._mockContext);
TracePaymentAttemptResponse response = facade.TracePaymentAttempt(request);
//My asserts
}
ファサード:私はリポジトリを書いたか最後に
public PaymentAttemptTrace SavePaymentAttemptResult(string customerCode, string transactionCode, ...)
{
//here the problem... PaymentAttemptTrace is the entity of entity framework.. Here i do the NEW of the object.. It should be injected, but I think it would be a wrong solution
PaymentAttemptTrace trace = new PaymentAttemptTrace();
trace.customerCode = customerCode;
trace.InvoiceId = idInvoice;
trace.PaymentDate = paymentDate;
trace.Result = result;
trace.Email = email;
trace.Terminal = terminal;
trace.EasypayCode = transactionCode;
trace.Amount = amount;
trace.creditCardId = idCreditCard;
trace.PaymentMethod = paymentMethod;
Repository<PaymentAttemptTrace> repository = new Repository<PaymentAttemptTrace>(base.Context);
repository.Insert(trace);
return trace;
}
::私はPaymentsManager
を開発した方法をここで
public TracePaymentAttemptResponse TracePaymentAttempt(TracePaymentAttemptRequest request)
{
TracePaymentAttemptResponse response = new TracePaymentAttemptResponse();
try
{
...
_unitOfWork.PaymentsManager.SavePaymentAttemptResult(
easyPay.CustomerCode,
request.CodiceTransazione,
request.EsitoPagamento + " - " + request.DescrizioneEsitoPagamento,
request.Email,
request.AliasTerminale,
request.NumeroContratto,
easyPay.IdInvoice,
request.TotalePagamento,
paymentDate);
_unitOfWork.Commit();
response.Result = ResponseResult.Success;
}
catch (Exception ex)
{
response.Result = ResponseResult.Fail;
response.ResultMessage = ex.Message;
}
return response;
}
public class Repository<TEntity>
where TEntity : class
{
internal PublicAreaContext _context;
internal DbSet<TEntity> _dbSet;
public Repository(IDataContext context)
{
//the context is mocked.. Its type is {Castle.Proxies.PublicAreaContextProxy}
this._context = context as PublicAreaContext;
//the entity is not mocked. Its type is {PaymentAttemptTrace} but should be {Castle.Proxies.PaymentAttemptTraceProxy}... so _dbSet result NULL
this._dbSet = this._context.Set<TEntity>();
}
public virtual void Insert(TEntity entity)
{
//_dbSet is NULL so "Object reference not set to an instance of an object" exception is raised
this._dbSet.Add(entity);
}
}
エンティティの挿入/更新に関するテストを表示して、どのように正確に失敗するか説明してください。また、テスト対象のコードも参考になります。 –
私の質問を例文 – Ciccio