1 #region Copyright © 2003-2008 Richard Beauchamp <rbeauchamp@gmail.com> 2 3 /* 4 * DomainObjects for .NET 5 * Copyright © 2003-2008 Richard Beauchamp 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 22 #endregion 23 24 using System; 25 using System.Collections.Generic; 26 using DomainObjects.Facade.Command; 27 using DomainObjects.Facade.Domain; 28 using DomainObjects.Facade.Test; 29 using DomainObjects.Test.Domain; 30 using DomainObjects.Test.TestType.Service; 31 using NUnit.Framework; 32 33 namespace DomainObjects.Test.TestFixture 34 { 35 /// <summary> 36 /// Test that DomainObjects makes appropriate calls to the 37 /// callback interfaces ITransactionAware, ITransactionSetAware, 38 /// and IReconstructionAware. 39 /// </summary> 40 [TestFixture] 41 public class CallbackTests : DomainObjectsTestFixture 42 { 43 #region ITransactionAware callback interface tests 44 45 [Test] 46 public void BeforeAndAfterCommitOnBoundObject() 47 { 48 Product newProduct = CreateProduct(); 49 PersistenceFacade.Persist(newProduct); 50 Assert.IsTrue(newProduct.BeforeCommitWasCalled, "BeforeCommit() was called."); 51 Assert.IsTrue(newProduct.AfterCommitWasCalled, "AfterCommit() was called."); 52 } 53 54 #endregion 55 56 57 #region IExecutionAware callback interface tests 58 59 [Test] 60 public void BeforeAndAfterExecutionTest() 61 { 62 Product newProduct = CreateProduct(); 63 PersistenceFacade.Persist(newProduct); 64 Assert.IsTrue(newProduct.BeforeExecuteAllSentencesWasCalled, "BeforeExecuteAllSentences() was called."); 65 Assert.IsTrue(newProduct.AfterExecuteAllSentencesWasCalled, "AfterExecuteAllSentences() was called."); 66 Assert.IsTrue(newProduct.AfterExecuteAndCommitWasCalled, "AfterExecuteAndCommit() was called."); 67 Assert.IsTrue(newProduct.BeforeExecuteWasCalled, "BeforeExecute() was called."); 68 Assert.IsTrue(newProduct.AfterExecuteWasCalled, "AfterExecute() was called."); 69 70 newProduct.Name = "Update the Product"; 71 PersistenceFacade.Persist(newProduct); 72 73 newProduct.Name = "RollbackMe"; 74 75 try 76 { 77 PersistenceFacade.Persist(newProduct); 78 } 79 catch 80 { 81 } 82 83 ClearAppDomainAndContextCache(); 84 85 Product product = QueryFacade.FindObjectByPrimaryKey<Product>(newProduct.PrimaryKey); 86 87 Assert.AreEqual("Update the Product", product.Name, "The name is 'Update the Product'. The last execution was cancelled"); 88 } 89 90 #endregion 91 92 #region IReconstructionAware callback interface tests 93 94 [Test] 95 public void OnAfterReconstructionCalled() 96 { 97 // The class Product implements the IReconstructionAware interface. 98 // Setup test by creating and persisting a Product instance. 99 Product newProduct = CreateProduct(); 100 PersistenceFacade.Persist(newProduct); 101 102 // Get the Product primary key for later use. 103 object productPrimaryKey = newProduct.PrimaryKey; 104 105 // Clear the cache so that the Product instance will 106 // be reconstructed from the database rather than being 107 // retrieved from the cache. 108 ClearAppDomainAndContextCache(); 109 110 // Query for the product so that DomainObjects retrieves the instance from 111 // the database and calls OnAfterReconstruction(). 112 Product productFromDb = Query.FindObjectByPrimaryKey<Product>(productPrimaryKey); 113 Assert.IsTrue(productFromDb.OnAfterReconstructionWasCalled, "OnAfterReconstruction() was called."); 114 } 115 116 /// <summary> 117 /// Reproduces the bug '[ 1522191 ] OnAfterReconstructor Issue'. 118 /// Tests the if a query occurs when OnAfterReconstruction is called, 119 /// DomainObjects retrieves the results without throwing a 'System.InvalidOperationException' 120 /// because 'There is already an open DataReader associated with this Command which must be closed first.' 121 /// </summary> 122 [Test] 123 public void QueryDuringOnAfterReconstructionDoesNotCauseException() 124 { 125 ProductCategory productCategory = new ProductCategory("ProductCategoryName", "ProductCategoryDescription").Manage<ProductCategory>(); 126 Product newProduct1 = new Product(productCategory, "ProductName1").Manage<Product>(); 127 Product newProduct2 = new Product(productCategory, "ProductName2").Manage<Product>(); 128 129 PersistenceFacade.Persist(newProduct1, newProduct2, productCategory); 130 Key productCategoryPrimaryKey = productCategory.PrimaryKey; 131 ClearAppDomainAndContextCache(); 132 Criteria criteria = new Criteria(); 133 criteria.AddEqualTo(Types.Product.Field._productCategoryId, productCategoryPrimaryKey[0]); 134 List<Product> productsFromDb = QueryFacade.FindObjectSet<Product>(criteria); 135 foreach (Product productFromDb in productsFromDb) 136 { 137 Assert.IsTrue(productFromDb.OnAfterReconstructionWasCalled, "OnAfterReconstruction() was called."); 138 } 139 } 140 141 #endregion 142 143 144 #region ITransactionSetAware callback interface tests 145 146 [Test] 147 public void BeforeAndAfterCommitOnITransactionSetAware() 148 { 149 Product newProduct = CreateProduct(); 150 PersistenceFacade.Persist(newProduct); 151 Assert.IsTrue(!TransactionSetAware.BeforeCommitCalled, "BeforeCommit() was not called."); 152 Assert.IsTrue(!TransactionSetAware.AfterCommitCalled, "AfterCommit() was not called."); 153 154 // TransactionalAwareService defines the 155 // TransactionAttribute(TransactionOption transactionOption, Type transactionAwareType) attribute 156 Product newProduct2 = CreateProduct(); 157 TransactionSetAwareService.Instance.Persist(newProduct2); 158 Assert.IsTrue(TransactionSetAware.BeforeCommitCalled, "BeforeCommit() was called."); 159 Assert.IsTrue(TransactionSetAware.AfterCommitCalled, "AfterCommit() was called."); 160 } 161 162 [Test] 163 public void OnAbortCalledOnITransactionSetAware() 164 { 165 try 166 { 167 TransactionSetAwareService.Instance.ThrowException(); 168 } 169 catch 170 { 171 // nothing to do 172 } 173 Assert.IsTrue(TransactionSetAware.OnAbortCalled, "OnAbort() was called."); 174 } 175 176 #endregion 177 178 179 private static Product CreateProduct() 180 { 181 Product product = new Product(GetProductCategory(1), DateTime.Now.Ticks.ToString()).Manage<Product>(); 182 product.Name = "CallbackTests Product"; 183 product.IsSelloutProduct = true; 184 product.MinimumStock = 100; 185 product.OrderedUnits = 17; 186 product.PricePerUnit = 0.45M; 187 product.CurrentStock = 234; 188 product.Unit = "bottle"; 189 return product.Manage<Product>(); 190 } 191 192 private static ProductCategory GetProductCategory(int primaryKey) 193 { 194 return Query.FindObjectByPrimaryKey<ProductCategory>(primaryKey); 195 } 196 } 197 }