Witam,
jak w temacie staram się napisać metodę testową dla metody, która jest w asynchroniczny sposób wyciąga dane z bazy.
Sama metoda wygląda w uproszczeniu tak:
public async Task<MyViewModel> GetData(long id)
{
try
{
//_database to instancja DbContext wstrzykiwana do konstruktora serwisu
var query = await (from invoice in _database.Invoice
//tutaj kilka joinów
where invoice.id == id
select new { /* tutaj selecty właściwych obiektów */ }).ToListAsync();
var model = query.Select(r => new MyViewModel()
{
//tutaj mapuję na MyViewModel, którego pola tu struktury
}).FirstOrDefault();
return model;
}
catch (Exception ex)
{
log.Error(ex.Message);
return null;
}
}
Ok, metoda działa. Czas na napisanie testu dla niej.
[TestClass]
public class MyServiceTest
{
private IMyService _service;
private Mock<ApplicationDbContext> _db;
[TestInitialize]
public void Initialize()
{
_db = new Mock<ApplicationDbContext>();
}
[TestMethod]
public async Task GeData_ShouldReturnElement()
{
//ARRANGE
var invoices = Builder<invoice>.CreateListOfSize(3).Build();
var invoicesStates = Builder<invoice_state>.CreateListOfSize(3).Build();
//i tak dalej dla każdej tabeli użytej w joinie
_db.Setup(x => x.Invoice).Returns(this.SetupMock<invoice>(invoices).Object);
_db.Setup(y => y.InvoiceState).Returns(this.SetupMock<invoice_state>(invoicesStates).Object);
//i tak dalej dla każdej tabeli użytej w joinie
_service = new MyService(_db.Object);
//ACT
var result = await _service.GetData(2);
//ASSERT
Assert.IsNotNull(result);
Assert.IsInstanceOfType(result, typeof(MyViewModel));
Assert.AreEqual(result.Id, 2);
}
private Mock<DbSet<T>> SetupMock<T>(IList<T> entities) where T : class
{
var mockSet = new Mock<DbSet<T>>();
mockSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(entities.AsQueryable().Provider);
mockSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(entities.AsQueryable().Expression);
mockSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(entities.AsQueryable().ElementType);
mockSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(entities.GetEnumerator());
mockSet.Setup(m => m.Add(It.IsAny<T>())).Callback<T>((s) => entities.Add(s));
return mockSet;
}
}
result jest zawsze nullem. Jeżeli testowaną metodę zrobię synchroniczną to test przechodzi.
Gdzie leży problem?