chevron-thin-right chevron-thin-left brand cancel-circle search youtube-icon google-plus-icon linkedin-icon facebook-icon twitter-icon toolbox download check linkedin phone twitter-old google-plus facebook profile-male chat calendar profile-male
Welcome to Typemock Community! Here you can ask and receive answers from other community members. If you liked or disliked an answer or thread: react with an up- or downvote.
0 votes
I have the following test:

public void Load()
    INestedUnitOfWork unitOfWork = Isolate.Fake.Instance<INestedUnitOfWork>();
    IAmazonCredentials credentials = Isolate.Fake.Instance<IAmazonCredentials>();
    AmazonCredentialsForm view = Isolate.Fake.Instance<AmazonCredentialsForm>();

    WizardPresenter wp = Isolate.Fake.Instance<WizardPresenter>();

    AmazonCredentialsFormPresenter presenter = new AmazonCredentialsFormPresenter(unitOfWork, credentials, view);
    Isolate.Invoke.Event(() => view.Load += null);

    Isolate.Verify.WasCalledWithAnyArguments(() => wp.ConfigureButtons());
    Isolate.Verify.WasCalledWithAnyArguments(() => view.NameTextEdit.Focus());

The view.Load event is wired up in the constructor of the AmazonCredentialsFormPresenter to a private function:
void mView_Load(object sender, EventArgs e)

The test is failing on the Isolate.Invoke.Event line with a System.NullReferenceException. I've tried a few variations, such as:
Isolate.Invoke.Event(() => view.Load += null, EventArgs.Empty);
Isolate.Invoke.Event(() => view.Load += null, this, EventArgs.Empty);
but all give the same result.

What am I missing here?
asked by dougclutter (3.5k points)

15 Answers

0 votes

Can you post the IRootCollection interface code? I'd like to see if there's anything out of the ordinary there. Also, what behavior are you seeing? The previous issues we encountered were of exceptions being thrown from Invoke.Event(), but this seems different.

Typemock Support
answered by doron (16.5k points)
0 votes
It is a rather complex interface as its name implies it is a root for the entire application:

   public interface IRootCollection : IStorableCollection {
      void Reinitialize(ISerializationContext context);
      string ProjectIdentifier { get ; }
      UsageLevel LicensingLevel { get; }
      Mnemonic ServerProjectId { get; }
      ILocalSettingsProvider Settings { get; }
      IDisplayManager DisplayManager { get; }
      IComposition CurrentComposition { get; set; }
      IStorable CurrentCadContext { get; set; }
      IInitialSite InitialSite { get; }
      IMnemonicPath CurrentSite { get; set;}
      Matrix4D CurrentTransform { get; set;}
      ISiteTableInstance SiteTable { get; }
      ILegacyMslinkTableInstance LegacyMslinkTable { get; }
      IDataSetManager DataSetManager { get; }
      IPrivilegeController PrivilegeController { get; }
      bool IsReadonly { get; }
                event PropertyChangeEventHandler CadContextChanged;

It extends another interface

   public interface IStorableCollection : IStorable {
      void Serialize (ISerializationContext context, Predicate<IMnemonicPath> filter);
      void SerializeDeep (ISerializationContext context, Predicate<IMnemonicPath> filter);
      void SerializeDeep(ISerializationContext context);
      IStorable Resolve(IMnemonicPath path);
      IMnemonicPath NewMnemonic (IInternalId internalId, ICollection exclusions);
      IMnemonicPath GetChildPath(IStorable child, IMnemonicPath tail);
      Mnemonic AddChild(string mnemonicCandidate, IStorable child, IChangeScope scope);
        void RemoveChild (Mnemonic child, string description);
      void Drop(IMnemonicPath child, bool refreshDisplay);
      void RemoveChildren ();

Which extends another interface:

   public interface IStorable : IDisposable, IDescribable {
      void Serialize(ISerializationContext context);
      int CompareInternalId (IInternalId id);
      StorableStatusOverlays Status { get; }
        IPropertyProvider PropertyProvider { get; }
      void OnIntegrate (ISerializationContext newContext);
      IMnemonicPath Path { get; }
      void AddStoreExtender (IStoreExtender extender);
      void RemoveStoreExtender (Mnemonic extenderType, string extenderId);
      bool AutoResolve (IConflictManager conflictManager, IAggregateConflict aggreateConflict);
      int BaseRevision { get; set; }
      IChangeManager ChangeManager { get; }

Which is disposable and extends another interface

   public interface IDescribable {
      object Describe(IDescribeContext context);

In all this, there is only one event (a custom event that basically is to fire when something changes and provides the old and new versions.

When we attach an event and try to fire it, nothing happens. No exceptions, no method execution - i.e. no side effects of trying to fire the event. Here the event:

   public class PropertyChangeEventArgs : EventArgs {
      public readonly object Old;
      public readonly object New; 
      public PropertyChangeEventArgs (object oldObj, object newObj) : base () {
         Old = oldObj;
         New = newObj;
   public delegate void PropertyChangeEventHandler (object sender, PropertyChangeEventArgs args);

I hope this helps.
answered by sellingerd (5.7k points)
0 votes

The reason nothing happens when you fire the event is because when you created the fake you used the default which is recursive fakes.
When you added the event handler in the line:
rootCollection.CadContextChanged += new PropertyChangeEventHandler ...

The event's add method was ignored.
to solve this you can either create the fake with call original default behavior or set the behavior of the add method to call original.

public void TestProblem () 
   //IRootCollection rootCollection = Isolate.Fake.Instance<IRootCollection> (Members.CallOriginal);  option 1
   IRootCollection rootCollection = Isolate.Fake.Instance<IRootCollection> ();
   Isolate.WhenCalled(() => fake.CadContextChanged += null).CallOriginal(); //  option 2
   bool fired = false;
   rootCollection.CadContextChanged += new PropertyChangeEventHandler ((sender, args) => { fired = true; });
   Isolate.Invoke.Event (() => rootCollection.CadContextChanged += null, null, null);
   Assert.IsTrue (fired);

Please let me know if it helps.
answered by ohad (35.5k points)
0 votes
We have tried this using the following test:

      public void TestProblem () {
         IRootCollection rootCollection = Isolate.Fake.Instance<IRootCollection> (Members.CallOriginal); // option 1
         //IRootCollection rootCollection = Isolate.Fake.Instance<IRootCollection> ();
         //Isolate.WhenCalled (() => rootCollection.CadContextChanged += null).CallOriginal (); //  option 2
         bool fired = false;
         rootCollection.CadContextChanged += new PropertyChangeEventHandler ((sender, arg) => { fired = true; });
         Isolate.Invoke.Event (() => rootCollection.CadContextChanged += null, null, null);
         Assert.IsTrue (fired);

But we get an class cast exception saying that it can not cast our event into a System.EventHandler

System.InvalidCastException : Impossible d'effectuer un cast d'un objet de type 'FireEvent.PropertyChangeEventHandler' en type 'System.EventHandler'.

Any suggestions?
answered by sellingerd (5.7k points)
0 votes

I'll look into this and see if I can recreate this locally. We are currently working on fixing some bugs in event invocation, and I'll keep you up to date with our progress.

Typemock Support
answered by doron (16.5k points)