如何为此业务逻辑代码编写可靠的unit testing?

我得到了一些我想测试的业务逻辑代码。
目前我只知道如何在没有其他依赖关系的逻辑代码上编写unit testing。

任何人都可以指出我如何测试这个function的好方向,也许举个例子?

是测试这个集成测试的唯一方法还是我必须使用mock / stub?

///  /// Gets the scan face file by a MemberID ///  /// The ID of a member /// A scan face file in byte array format 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; } 

CHANGES(我实现了Repository和rhino mocks):

BL:

 public byte[] GetScanFileFaceByMemberID(int MemberID) { byte[] scanFileFace; var query = Repository.GetAll().Where(bl => bl.MEMBERID == MemberID).Single(); scanFileFace = query.scanFileFace; return scanFileFace; } 

unit testing:

 [TestMethod] public void GetScanFileFace_ExistingScan_ReturnByteArray() { //Make testScan List testScan = PrepareTestDataScan(); //Arrange KlantenBL klantenBL = new KlantenBL(); klantenBL.Repository = MockRepository.GenerateMock(); klantenBL.Repository.Stub(bl => bl.GetAll()).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 PrepareTestDataScan() { List scans = new List(); //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 GetAll() { DZine_IStyling_ProductionEntities context = GetObjectContext(); IList list = context .CreateQuery( "[" + typeof(T).Name + "]") .ToList(); ReleaseObjectContextIfNotReused(); return list; } public IList GetAll(Func expression) { DZine_IStyling_ProductionEntities context = GetObjectContext(); IList list = context .CreateQuery( "[" + typeof(T).Name + "]") .Where(expression) .ToList(); ReleaseObjectContextIfNotReused(); return list; } 

这完全归功于所有人!

依我看来…

如果您直接通过DataBaseEntities上下文(ProductionEntities)与数据库进行交互,那么您的逻辑将无法测试。 因为你的逻辑依赖于ProductionEntities。

我建议您按照数据库访问层的存储库模式 。 您将能够使代码成为可测试性逻辑。 该模式将帮助您从逻辑中注入数据访问层。

我还建议你遵循dependency injection模式。 此模式将帮助您更轻松地对代码进行unit testing。 您将能够使用像Rhino mock这样的模拟框架来帮助您进行unit testing。

这看起来不像是一块业务逻辑,而是一块数据访问。

可以通过接口使用dependency injection来存储您的ProductionEntities,使用lambda来确保您的“使用”以相同的方式工作:

 // Use this in real code public class MyClass() : MyClass(() => new ProductionEntities()) { } // Use this in your test public class MyClass(Func 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-keng所说的是公平的 – 使用存储库模式会有所帮助 – 但我认为这是属于存储库的代码。 看起来很简单,我不担心打破对数据的依赖。

您可以使用集成测试来测试这个部分,或者您可以只测试整个系统并确保它的这一部分与其他部分很好地配合。

如果您将每个测试视为如何使用代码的示例,则可能会有所帮助。 它不是真的可以测试你的代码,而是帮助你探索它应该和不应该做什么,以及其他人如何使用它。 如果仅在集成时使用代码才有意义,请编写集成测试。 否则,您可以使用上面的模式注入模拟。