[英]Unit testing: how to test methods with a lot of underlying objects and business logic
[英]How to write a solid unit test for this business logic code?
我得到了一些要測試的業務邏輯代碼。
目前,我只知道如何在沒有其他依賴項的邏輯代碼上編寫單元測試。
誰能為我指出如何測試此功能的良好方向,並舉個例子?
是測試此集成測試的唯一方法,還是必須使用模擬/存根?
/// <summary>
/// Gets the scan face file by a MemberID
/// </summary>
/// <param name="MemberID">The ID of a member</param>
/// <returns>A scan face file in byte array format</returns>
public byte[] GetScanFileFaceByMemberID(int MemberID)
{
byte[] scanFileFace;
using (ProductionEntities entityContext = new ProductionEntities())
{
scanFileFace = (from scan in entityContext.tblScan
where scan.MEMBERID == MemberID
select scan.scanFileFace).Single();
}
return scanFileFace;
}
更改(我實現了存儲庫和犀牛模擬):
BL:
public byte[] GetScanFileFaceByMemberID(int MemberID)
{
byte[] scanFileFace;
var query = Repository.GetAll<tblScan>().Where(bl => bl.MEMBERID == MemberID).Single();
scanFileFace = query.scanFileFace;
return scanFileFace;
}
單元測試:
[TestMethod]
public void GetScanFileFace_ExistingScan_ReturnByteArray()
{
//Make testScan
List<tblScan> testScan = PrepareTestDataScan();
//Arrange
KlantenBL klantenBL = new KlantenBL();
klantenBL.Repository = MockRepository.GenerateMock<IRepository>();
klantenBL.Repository.Stub(bl => bl.GetAll<tblScan>()).IgnoreArguments().Return(testScan);
//Act
var result = klantenBL.GetScanFileFaceByMemberID(2);
//assert
Assert.AreEqual(result.GetType().Name, "Byte[]");
Assert.AreEqual(result.Length, 10);
}
//Prepare some testData
private List<tblScan> PrepareTestDataScan()
{
List<tblScan> scans = new List<tblScan>();
//Declare some variables
byte[] byteFile = new byte[4];
byte[] byteFile10 = new byte[10];
DateTime date = new DateTime(2012,01,01);
scans.Add(new tblScan { SCANID = 1, MEMBERID = 1, scanFileFace = byteFile, Hair = byteFile, scanFileAvatar = byteFile, scanFileMeasurements = byteFile, scanDate = date });
scans.Add(new tblScan { SCANID = 2, MEMBERID = 2, scanFileFace = byteFile10, Hair = byteFile, scanFileAvatar = byteFile, scanFileMeasurements = byteFile, scanDate = date });
scans.Add(new tblScan { SCANID = 3, MEMBERID = 3, scanFileFace = byteFile, Hair = byteFile, scanFileAvatar = byteFile, scanFileMeasurements = byteFile, scanDate = date });
return scans;
}
倉庫:
public IList<T> GetAll<T>()
{
DZine_IStyling_ProductionEntities context = GetObjectContext();
IList<T> list = context
.CreateQuery<T>(
"[" + typeof(T).Name + "]")
.ToList();
ReleaseObjectContextIfNotReused();
return list;
}
public IList<T> GetAll<T>(Func<T, bool> expression)
{
DZine_IStyling_ProductionEntities context = GetObjectContext();
IList<T> list = context
.CreateQuery<T>(
"[" + typeof(T).Name + "]")
.Where(expression)
.ToList();
ReleaseObjectContextIfNotReused();
return list;
}
一切正常,謝謝!
依我看來...
您的邏輯無法測試您是否直接通過DataBaseEntities context(ProductionEntities)與數據庫進行交互。 因為您的邏輯取決於ProductionEntities。
我建議您遵循存儲庫模式進行數據訪問層。 您將能夠使您的代碼成為可測試性邏輯。 該模式將幫助您從邏輯注入數據訪問層。
我還建議您遵循依賴項注入模式。 此模式將幫助您更輕松地對代碼進行單元測試。 您將能夠使用Rhino模擬之類的模擬框架來幫助您進行單元測試。
這看起來不像業務邏輯,而是數據訪問。
您可以通過接口使用依賴項注入來生產ProductionEntities,並使用lambda來確保您的“ using”以相同的方式工作:
// Use this in real code
public class MyClass() : MyClass(() => new ProductionEntities())
{
}
// Use this in your test
public class MyClass(Func<IHaveEntities> entities)
{
_entities = entitites;
}
public byte[] GetScanFileFaceByMemberID(int MemberID)
{
byte[] scanFileFace;
using (IHaveEntities entityContext = _entities())
{
scanFileFace = (from scan in entityContext.tblScan
where scan.MEMBERID == MemberID
select scan.scanFileFace).Single();
}
return scanFileFace;
}
但是,我認為這太過分了。 在某些時候,您確實需要訪問數據。 什么@ pongsathon鏗說是公平的-使用存儲庫模式將幫助-但我認為這是在倉庫中屬於代碼。 看起來很簡單,我不必擔心打破對數據的依賴。
您可以只使用集成測試來測試此部分,也可以只測試整個系統,並確保該部分與其他部分配合良好。
如果您將每個測試都看作是如何使用代碼的示例,則可能會有所幫助。 測試代碼並不能真正幫助您探究它應該做和不應該做的事情以及其他人如何使用它。 如果僅在集成時使用代碼有意義,請編寫集成測試。 否則,您可以使用上述模式來注入模擬。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.