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'm using a Windows TreeView which has a presenter for the tree itself (TreePresenter), plus a different presenter for each type of node (such as NodePresenter). The NodePresenter uses its reference to the TreePresenter to access the tree, so that it can add and delete its own type of nodes.

The following test instantiates a NodePresenter using a fake TreePresenter. Then the NodePresenter's AddNode method should add a node to the root of the tree by calling the TreeView.Nodes.Add method, but instead I get a message that the expected method was not called.

        [Test]
        public void AddNode()
        {
            TreePresenter treePresenter = Isolate.Fake.Instance<TreePresenter>();
            NodePresenter nodePresenter = new NodePresenter( treePresenter );
            Isolate.WhenCalled( () => nodePresenter.TreePresenter.Tree.Nodes.Add( "name" ) ).
                    WillReturn( new TreeNode() );

            nodePresenter.AddNode();

            Isolate.Verify.WasCalledWithAnyArguments( () => 
                nodePresenter.TreePresenter.Tree.Nodes.Add( "name" ) );
        }


Here's the code for the Node and Tree presenters.

    public class NodePresenter
    {
        private TreePresenter _treePresenter;

        public NodePresenter( TreePresenter treePresenter )
        {
            _treePresenter = treePresenter;
        }
        
        public TreePresenter TreePresenter
        {
            get { return _treePresenter; }
        }

        public void AddNode()
        {
            TreeNode systemNode = _treePresenter.Tree.Nodes.Add( "name" );
        }
  }

    public interface ITreeView
    {
        TreeView TreeView { get; set; }
    }

    public class TreePresenter
    {
        ITreeView     _view;
        NodePresenter _nodePresenter;

        public TreePresenter( ITreeView view )
        {
            _view = view;
            _nodePresenter = new NodePresenter( this );
        }
        
        public TreeView Tree
        {
            get { return _view.TreeView; }
        }

        public void Run()
        {
            _nodePresenter.AddNode();
        }
  }
:(
asked by denisv (2.8k points)

4 Answers

0 votes
I'm not sure, but you could try mocking your NodePresenter...


[Test(), Isolated()]
        public void AddNode()
        {
            TreePresenter treePresenter = Isolate.Fake.Instance<TreePresenter>();
            NodePresenter mock = Isolator.Fake.Instance<NodePresenter>(Members.CallOriginal);
            Isolator.Swap.NextInstance<NodePresenter>().With(mock);

            NodePresenter nodePresenter = new NodePresenter( treePresenter );
            Isolate.WhenCalled( () => nodePresenter.TreePresenter.Tree.Nodes.Add( "name" ) ).
                    WillReturn( new TreeNode() );

            nodePresenter.AddNode();

            Isolate.Verify.WasCalledWithAnyArguments( () =>
                nodePresenter.TreePresenter.Tree.Nodes.Add( "name" ) );
        } 


I'm not quite clear myself on the 'correct' way to tests against a long chain of calls like this...

HTH
answered by boo (21.8k points)
0 votes
Hi,

It happens because nodePresenter.TreePresenter is a field, which messes up the verification of the entire chain. (I can see what you want it to do, though, and it makes sense).

try replacing the verification statement with this instead:
Isolate.Verify.WasCalledWithAnyArguments( () => 
                treePresenter.Tree.Nodes.Add( "name" ) ); 



this time, it starts with the fake TreePresenter instead of the field. Please confirm that it worked for you.
answered by gilz (14.5k points)
0 votes
Hi Gil,

Yes, that worked. Thanks for your help!

This recursive faking is great. I see that the examples in the documentation show a chain of method calls, whereas I've got a chain of properties. So is the rule that you can chain either methods or properties as long as you start with the faked object?

Just another quick (but unrelated) question: If I fake a future instance by calling Isolate.Fake followed by Isolate.Swap.NextInstance, how can I check if the constructor was called on the fake object type? I've worked out how to do it with Natural and Reflective Mocks, but not with AAA.

Denis
answered by denisv (2.8k points)
0 votes
Hi,

The rule is don't have a field in the chain. All methods, properties and indexers work.

As for constructors the rule is (currently, we're adding stuff in the next release): If you use Isolate.Fake<>(Member.CallOriginal) the constructor gets called. With any other option (recursives fakes, return nulls or must specify return values) the constructor does not get called.

But, tf you're question is how to verify that a constructor got called, then AAA doesn't have that. Yet.

Cheers
answered by gilz (14.5k points)
...