I had a quick look at RollbackAttribute source code and it's use of EnterpriseServices to enter, leave and abort the transaction.
I can probably bring that ROllback code into the test method, and wait after the transaction was complete, but how do I rollback the transaction without simply aborting it? Can I hold a token on a transaction and undo it later? Or can I acquire a reference to the EnterpriseServices transaction object and pass it onto the ReminderManager? All of this would be so much easier if MS ORM was mockable :( Thanks again Jeff On Dec 30, 9:53 pm, CVertex <[EMAIL PROTECTED]> wrote: > Thanks Jeff. What DAL library do you use that has good testability? > > Everything about MS ORM is great except for the testabiliti-ness. > > Do you know how i could go about solving this problem, or who to ask > about it? > > Happy holidays, > Vijay > > On Dec 30, 8:25 pm, "Jeff Brown" <[EMAIL PROTECTED]> wrote: > > > I think what's happening is that there are two different transaction > > contexts in play -- one for each thread. > > > The main thread of the test runs in one transaction context provided by the > > [Rollback] attribute and the background thread is probably getting its own > > transaction context. Because the first transaction has not been committed > > yet (thanks to [Rollback] the second transaction cannot see the changes that > > were made. > > > Just a guess. > > > If this is indeed the case, then you'd need to ensure that the operations > > performed by the ScheduleTimer thread get enlisted in the transaction > > context of the main test thread somehow. I'm afraid I don't know how to > > help you with that off-hand since I've not worked with the MS ORM stuff > > myself. > > > Happy holidays, > > Jeff. > > > -----Original Message----- > > From: [email protected] [mailto:[EMAIL PROTECTED] On > > > Behalf Of CVertex > > Sent: Saturday, December 29, 2007 11:35 PM > > To: MbUnit.User > > Subject: MbUnit Rollback Threaded Issues > > > Hi Guys, > > > I'm a new TDD'er and I'm already witnessing significant increases in bug > > findings in my own code. I can't understand how I built software in the past > > without MbUnit and Rhino Mocks. I support webforms was a big set back, but > > now that MS MVC is in the works, i'm building more reliable sites already. > > > The idea of creating mock harnesses, environments and relationships is kinda > > addictive for exploring the limits of function. But, when I can't think of a > > good way to test my DAL. Now 3.5 is out, I've jumped onto LINQ-to-SQL ORM > > cos it's so well implemented, but unit testing it isn't very easy. For those > > that have jumped onto MS ORM, is there a general pattern I can follow to > > unit test my DAL? > > > Since I can't mock or fake my DAL, I'm writing to the database in each test > > and relying on RollbackAttribute to erase the changes. This works great for > > simple single threaded tests, but I'm having issues accessing database > > changes in a thread separate to the [Test] method. > > > I'm trying to test a simple scheduling system. The code for the class > > is: > > > public class ReminderManager { > > public const string ReminderManagerKey = "ReminderManager"; > > > private ScheduleTimer timer = new ScheduleTimer(); > > public ScheduleTimer Timer { get { return timer; } } > > > private DateTime lastCheckTime = DateTime.Now; > > public DateTime LastCheckTime { get { return lastCheckTime; } } > > > public event Schedule.ExceptionEventHandler CheckError > > { > > add > > { > > timer.Error += value; > > } > > > remove > > { > > timer.Error -= value; > > } > > } > > > public void SetUpTimer(IScheduledItem schedule) { > > timer.AddJob(schedule, new Action(CheckForReminders)); > > timer.Start(); > > } > > public void TearDownTimer() { > > timer.Stop(); > > } > > > protected virtual void CheckForReminders() { > > > DateTime now = DateTime.Now; > > > // check for reminders between now and last event > > CharlesNicholasDataContext db = new > > CharlesNicholasDataContext(); > > var reminders = from r in db.Reminders where > > r.DateTime>lastCheckTime && r.DateTime<=now > > select r; > > > int numrems = db.Reminders.Count(); > > foreach (var reminder in reminders) { > > Launch(reminder); > > } > > > // update last checked > > lastCheckTime = now; > > } > > > protected virtual void Launch(Reminder reminder) > > { > > string message = "{3} Should send SMS to {0} on number {1}"; > > Console.WriteLine(message, reminder.Client.FirstName, > > reminder.Client.MobileNumber,reminder.DateTime.ToShortTimeString()); > > } > > > } > > > My First test checks that CheckReminders is called periodically. I use the > > Test specific subclass pattern to override CheckReminder for the following > > test: > > [Test] > > [Duration(4000d)] > > public void EnsurePeriodicReminderChecking() > > { > > var rmtest = new ReminderManagerTest(); > > rmtest.SetUpTimer(HalfSecondSchedule()); > > System.Threading.Thread.Sleep(750); > > Assert.IsTrue(rmtest.NumberOfChecks == 2); // 2 includes start > > of timing AND first tick > > rmtest.TearDownTimer(); > > } > > > The second test is causing me grief - it needs to test that reminders of the > > specific criteria are actually discovered and launched. > > [Test] > > [RollBack] > > [Duration(4000d)] > > public void LaunchSms() { > > // add fake but valid db data > > var client = FakeClient(); > > db.Clients.InsertOnSubmit(client); > > db.SubmitChanges(); > > > var message = FakeMessage(); > > db.ReminderMessages.InsertOnSubmit(message); > > db.SubmitChanges(); > > > var rem = FakeReminder(); > > rem.ReminderMessageId = message.Id; > > rem.ClientId = client.Id; > > db.Reminders.InsertOnSubmit(rem); > > db.SubmitChanges(); > > > // run once off timer > > manager.SetUpTimer(OnceOff()); > > int numres = db.Reminders.Count(); > > System.Threading.Thread.Sleep(20000); > > > // TODO check sms message is launched > > // TODO check send sms return code is given > > > } > > > So, in the test thread, I create a fake reminder, message and client and > > submit to the database. Then in the ReminderManager > > CheckReminders() it needs to read those fake records and should find the > > fake records. > > > In the [Test] method, the numRes integer is 2, but in the > > CheckReminders() method, numRes is 1. It's like the db changes in the first > > thread aren't visible from the second, even though no exception is thrown. > > > Is there an obvious explanation for that? Will the removal of Rollback make > > the database changes visible from the ReminderManager ScheduleTimer thread? > > > This is a bit mind boggling. > > > Thanks for your help, > > -Vijay --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "MbUnit.User" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/MbUnitUser?hl=en -~----------~----~----~----~------~----~------~--~---
