This project is read-only.

UnitTestContext context = GetContext();

Mar 19, 2012 at 9:14 PM

Thanks for sharing this code.  I have gone through all of the posts but haven't found where the UnitTextContext has been defined, nor the GetContext() method.    Am I missing some reference?

Mar 19, 2012 at 9:44 PM

It's defined on the base class called TestBase: http://unitdriven.codeplex.com/SourceControl/changeset/view/63998#784700

So that example should be this.GetContext() probably. 

Here is an example of a real world usage of TestDriven in the CSLA project:
http://www.lhotka.net/cslacvs/viewvc.cgi/core/trunk/Source/Csla.test/BusyStatus/BusyStatusTests.cs?view=markup 

Mar 19, 2012 at 9:53 PM

Thanks Justin. I appreciate your help.  Good work.

Javed

Mar 20, 2012 at 7:06 PM

I have only one TestMethod so far, with the folowing code:
[TestMethod]
        public void GetPersonListTest()
        {
            UnitTestContext context = GetContext();
            BackgroundWorker worker = new BackgroundWorker();
            var vm = new SilverlightApp.PersonListViewModel();
            worker.DoWork += (o, e) =>
            {
                vm.SearchingFor = "adam";
                vm.SearchType = 1;
                vm.GetPersonList();
            };
            worker.RunWorkerCompleted += (o, e) =>
            {
                var Lst = vm.Model;
                context.Assert.IsNotNull(Lst);

            };
            worker.RunWorkerAsync();

            context.Complete();
        }

But I am getting the following error right off the bat with the code landing in the RunWorkerCompleted section.  The test itself times out after 3-5 seconds.

error {System.UnauthorizedAccessException: Invalid cross-thread access.
   at MS.Internal.XcpImports.CheckThread()
   at System.Windows.DependencyObject.GetValueInternal(DependencyProperty dp)
   at System.Windows.DependencyObject.GetValue(DependencyProperty dp)
   at Csla.Xaml.ViewModelBase`1.get_Model()
   at Csla.Xaml.ViewModelBase`1.SetProperties()
   at Csla.Xaml.ViewModelBase`1.OnSetProperties()
   at Csla.Xaml.ViewModelBase`1.set_IsBusy(Boolean value)
   at Csla.Xaml.ViewModelBase`1.BeginRefresh(String factoryMethod, Object[] factoryParameters)} System.Exception {System.UnauthorizedAccessException}

The code in PersonListViewModel is quite simple;

    public class PersonListViewModel  : Csla.Xaml.ViewModel<DispensableDrugList>
    {
        public PersonListViewModel  () {  ManageObjectLifetime = false;  }

        public void GetPersonList()
        {
            BeginRefresh("GetPersonList", _SearchingFor, _SearchType);
        }

    }

In normal usage that call has never failed.  Do I have my method set up wrong?

Javed

Mar 20, 2012 at 7:38 PM

It looks like calling GetPersonList() should not be done in the background thread. It has to be in the same thread that the object is created. I think you could create it in the DoWork lambda, and set it to e.Result = vm; And then cast it in RunWorkerCompleted to do your asserts (though you might get throws there too.

Also I think you want to wrap your context in a using(var context = GetContext()) { ... } block. But that's a different story.

Mar 20, 2012 at 9:11 PM

I changed the method and also decided to use a different ViewModel:

        [TestMethod]
        public void GetPersonTest()
        {
            UnitTestContext context = GetContext();
            using (context)
            {
                BackgroundWorker worker = new BackgroundWorker();
                worker.DoWork += (o, e) =>
                {
                    var vm = new PersonViewModel();
                    vm.GetPerson(161);
                    e.Result = vm;
                };
                worker.RunWorkerCompleted += (o, e) =>
                {
                    var vm = (PersonViewModel)e.Result;
                    var Lst = vm.Model;
                    context.Assert.IsNull(Lst);

                };
                worker.RunWorkerAsync();

            }

                context.Complete();
        }

The error is just about the same:

  <GlobalErrors>System.Reflection.TargetInvocationException: An exception occurred during the operation, making the result invalid.  Check InnerException for exception details. ---&gt; System.UnauthorizedAccessException: Invalid cross-thread access.
   at MS.Internal.XcpImports.CheckThread()
   at MS.Internal.ManagedPeerHelper.SetupManagedPeer(IManagedPeerBase managedPeer, NativeObjectSafeHandle&amp; nativeSafeHandle, UInt32 nativeTypeIndex, IntPtr constructDO, Nullable`1 isCustomType, Nullable`1 forceStrong)
   at System.Windows.DependencyObject..ctor(UInt32 nativeTypeIndex, IntPtr constructDO)
   at System.Windows.DependencyObject..ctor(UInt32 nativeTypeIndex)
   at System.Windows.DependencyObject..ctor()
   at Csla.Xaml.ViewModelBase`1..ctor()
   at Csla.Xaml.ViewModel`1..ctor()

When walking thru the code, the execution jumps from DoWork section to RunWorkerCompleted section right away, and I can then walk to the end of the method.  After4-5 seconds, the first line in RunWorkerCompleted gets highlighted again.  This time preessing Step Over simply exits the method.

Javed

Mar 20, 2012 at 9:17 PM

I bet that you can't call GetPerson() in the background thread. I think you have to do it in the main thread. Try the test without the backgroundworker at all. The implementation body of GetPerson will probably end up on another thread...

Mar 20, 2012 at 10:14 PM

You think something like this might do it !!

        [TestMethod]
        public void GetPersonTest()
        {
            var vm = new PersonViewModel();
            vm.GetPerson(161);
            vm.PropertyChanged += (o, ev) =>
            {
                if (ev.PropertyName == "Model")
                {
                    Assert.IsNotNull(vm.Model);
                }
            };


Wouldn't that be funny.  I do that a thousand time in my code already.

Javed

Mar 20, 2012 at 11:11 PM

There's one fly in the ointment. When the call goes to the Client side of Person object:

        public static void GetPerson(Int32 personKey, EventHandler<DataPortalResult<Person>> callback)
        {
            var dp = new DataPortal<Person>();
            dp.FetchCompleted += callback;
            dp.BeginFetch(personKey);
        }

The last line in the method above goes nowhere. I immediately end up in my OnError() method where it tells me that the DataPortal_Fetch() has not been implemented.  Using (context) {..} doesn't help. Why it wouldn't work - I don't know.

Javed

Mar 21, 2012 at 12:03 AM

Have you implemented DataPortal_Fetch on Person? My csla-fu is getting rusty...

Mar 21, 2012 at 12:43 AM

Yes, the DataPortal_Fetch() is implemented and has been working just fine.  Interestingly, from within a normal SL project, the same ViewModel, Person.Client and Person.Server files work like a charm.  It looks like the problem may be the two asynch calls, one after the other.  The first one is from the ViewModel to Person.Client and the second from the Parson.Client to Person.Server before the DataPortal_Fetch() is hit.  The first one seems to make it, but the second gets nowhere.

Javed

Mar 21, 2012 at 2:11 AM

You have to setup SL test project the same way as your main project.  You need to make sure server URL is the same in both cases and your server is accessible.  Your code is incorrect as well

[TestMethod]
public void GetPersonTest()
{

var context = GetContext();
var vm = new PersonViewModel();

vm.PropertyChanged += (o, ev) =>
{
if (ev.PropertyName == "Model")
{
  context.Assert.IsNotNull(vm.Model);

context.Complete();
}
};
vm.GetPerson(161);

Mar 21, 2012 at 3:27 AM

Sergey,

Thank you.  I rearranged the code exactly how you have written, but the result is the same.  Now in my normal Silverlight project this will work just fine.  But in the Silverlight Test Project, when I walk thru it, it goes to the line: dp.BeginFetch(personKey).  At that point, even when I click Step Into, I am immediately back in the ViewModel at the BeginRefresh() line, with the following error code.  When I stop testing and go back to normal operation, the same code works perfectly everytime.

DataPortal_Fetch not implemented
   at Csla.Reflection.MethodCaller.CallMethod(Object obj, String method, Boolean hasParameters, Object[] parameters)
   at Csla.Reflection.MethodCaller.CallMethod(Object obj, String method, Object[] parameters)
   at Csla.DataPortalClient.LocalProxy`1.BeginFetch(Object criteria, Object userState)
   at Csla.DataPortalClient.LocalProxy`1.BeginFetch(Object criteria)
   at Csla.DataPortal`1.BeginFetch(Object criteria)

I am going to try this with some other objects to see if anything else works differently.  You said, "You have to setup SL test project the same way as your main project."  I am creating the test project by choosing Silverlight under C# and then selecting Silverlight Unit Test Application.

Javed