我決定開始在我們的應用程序中編寫單元測試。它使用實體框架和存儲庫模式。單元測試EF存儲庫模式與Moq
現在我想開始測試使用存儲庫的邏輯類。我在這裏提供一個簡單的例子。
public class GenericRepository : IRepository
{
public IQueryable<TEntity> GetQuery<TEntity>() where TEntity : class
{
var entityName = GetEntityName<TEntity>();
return Context.CreateQuery<TEntity>(entityName);
}
private string GetEntityName<TEntity>() where TEntity : class
{
return typeof(TEntity).Name;
}
public IEnumerable<TEntity> Find<TEntity>(Expression<Func<TEntity, bool>> predicate) where TEntity : class
{
return GetQuery<TEntity>().Where(predicate).AsEnumerable();
}
}
一個簡單的邏輯類從日曆表中降序排列返回不同年(是的,我知道這個詞的日曆在我們的代碼拼寫錯誤):
我在班上GenericRepository三種方法
public class GetDistinctYearsFromCalendar
{
private readonly IRepository _repository;
public GetDistinctYearsFromCalendar()
{
_repository = new GenericRepository();
}
internal GetDistinctYearsFromCalendar(IRepository repository)
{
_repository = repository;
}
public int[] Get()
{
return _repository.Find<Calender_Tbl>(c => c.Year.HasValue).Select(c => c.Year.Value).Distinct().OrderBy(c => c).Reverse().ToArray();
}
}
這是我的第一個測試:
[TestFixture]
public class GetDistinctYearsFromCalendarTest
{
[Test]
public void ReturnsDistinctDatesInCorrectOrder()
{
var repositoryMock = new Mock<IRepository>();
repositoryMock.Setup(r => r.Find<Calender_Tbl>(c => c.Year.HasValue)).Returns(new List<Calender_Tbl>
{
new Calender_Tbl
{
Date =
new DateTime(2010, 1, 1),
Year = 2010
},
new Calender_Tbl
{
Date =
new DateTime(2010, 2, 1),
Year = 2010
},
new Calender_Tbl
{
Date =
new DateTime(2011, 1, 1),
Year = 2011
}
}.AsQueryable());
var getDistinct = new GetDistinctYearsFromCalendar(repositoryMock.Object).Get();
Assert.AreEqual(2, getDistinct.Count(), "Returns more years than distinct.");
Assert.AreEqual(2011, getDistinct[0], "Incorrect order, latest years not first.");
Assert.AreEqual(2010, getDistinct[1], "Wrong year.");
}
}
這工作正常。但這實際上並不是我想要做的。由於我必須在模擬對象上設置方法Find,所以我還需要知道它是如何在我的邏輯類中調用的。如果我想做TDD,我不想介意這個。我想知道的是我的存儲庫應該提供哪些日曆實體。我想設置GetQuery方法。 像這樣:
repositoryMock.Setup(r => r.GetQuery<Calender_Tbl>()).Returns(new List<Calender_Tbl>
{
new Calender_Tbl
{
Date =
new DateTime(2010, 1, 1),
Year = 2010
},
new Calender_Tbl
{
Date =
new DateTime(2010, 2, 1),
Year = 2010
},
new Calender_Tbl
{
Date =
new DateTime(2011, 1, 1),
Year = 2011
}
}.AsQueryable());
所以,當發現是在GenericRepository類內部調用GetQuery應該得到正確的日曆實體,我在安裝GetQuery。但這當然不起作用。由於我沒有設置我的模擬對象的查找方法,我沒有得到任何實體。
那該怎麼辦?當然,我可以使用鼴鼠或其他一些模擬一切的框架,但我不想那樣做。在課堂設計或測試中解決問題有什麼我可以做的嗎?
如果我不得不使用當前的解決方案,那麼世界並不是世界末日,但如果財產年度變成不可空的整數?那麼當然,我將不得不在邏輯類中更改我的實現,但我也必須更改測試。我想盡量避免這種情況。
我認爲這樣做是有「GetDistinctYearsFromCalendar」依賴於「IRepository」的一種方式。你可以模擬出「GenericRepository」的測試這樣「GetDistinctYearsFromCalendar」隔離。有關更多詳細信息,請參閱http://en.wikipedia.org/wiki/Dependency_injection。 – Michael
好吧,我沒有看到內部ctor。你在同一個項目中有測試和生產代碼嗎?我認爲正確的做法是完成依賴注入並跳過默認的ctor。 – Michael
我知道我可以只寫我的邏輯爲: 返回_repository.GetQuery(),其中(C => c.Year.HasValue)。選擇(C => c.Year.Value).Distinct()。 OrderBy(c => c).Reverse()。ToArray(); 沒有我一直測試到另一個項目,但暴露的內部用匯編指令的測試項目。 但是,如果我從來不使用另一種類型比GenericRepository呢?那麼是否需要一直進行依賴注入? 這似乎是最好的解決方案嗎?我是盲目的,想要使用存儲庫的所有功能。 –
John