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
-~----------~----~----~----~------~----~------~--~---

Reply via email to