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
Hi

i need to test the following code but cannot find a good approach to it please some one suggest a way


foreach (var feedContent in feedContents)
            {
                var taskbarNotifier = new TaskbarNotifier();
                while (taskbarNotifier.TaskbarState != TaskbarNotifier.TaskbarStates.hidden)
                    Application.DoEvents();
            }
asked by tolisss (28.8k points)

6 Answers

0 votes
Hi Tolisss,

I would need more information about what you are trying to test here but note the following:
  • * When you need to iteration over a collection of mocked types you can use the WhenCalled().WillReturnCollectionValuesOf() API to provide a collection of known test data

    * When you have a class initialization inside the code under test you can use the Future Object pattern through the Isolate.Swap.NextInstance<>().With() API

Please let us know if you have more detailed test requirements and I'll be happy to provide more pointed advice.

Thanks,
Doron
Typemock support
answered by doron (17.2k points)
0 votes
the code is as simple as the provided one.

what i need to test is that no taskbarnotifer will be constructed if the last instance of taskbarnotifer.TaskBarState not equal to hidden
answered by tolisss (28.8k points)
0 votes
Hi,
You are pushing it to the limits here.

Here is how you can do this using a state machine. for example if there are 3 feeds
[TestMethod,VerifyMocks]
public void no_taskbarNotifier_will_be_constructed_if_the_last_instance_of_taskbarnotifer_TaskBarState_not_equal_to_hidden()
{
    var mock = MockManager.MockAll<TaskbarNotifier>();
    var trackNotifier = mock.TrackInstances();
    // make sure that TaskbarState is not hidden when initialized
    trackNotifier.InitializeAction = instance => instance.TaskbarState = TaskbarNotifier.TaskbarStates.shown;

    var mockApplication = MockManager.Mock<Application>(Constructor.NotMocked);
    mockApplication.Do("DoEvents", e =>
    {   // 1st loop we have 1 TaskbarNotifier
        Assert.AreEqual(1, trackNotifier.Count);
    }  , e =>
    {   // 2nd loop we have 1 TaskbarNotifier - change State
        trackNotifier.LastInstance.TaskbarState = TaskbarNotifier.TaskbarStates.hidden;
        Assert.AreEqual(1, trackNotifier.Count);
    }  , e =>
    {   // 3rd loop we have 2 TaskbarNotifier
        Assert.AreEqual(2, trackNotifier.Count);
    }, e =>
    {   // 4th loop we have 2 TaskbarNotifier
        Assert.AreEqual(2, trackNotifier.Count);
    }, e =>
    {   // 5th loop we have 2 TaskbarNotifier - change State
        trackNotifier.LastInstance.TaskbarState = TaskbarNotifier.TaskbarStates.hidden;
        Assert.AreEqual(2, trackNotifier.Count);
    }, e =>
    {   // 6th loop we have 3 TaskbarNotifier - change State
        trackNotifier.LastInstance.TaskbarState = TaskbarNotifier.TaskbarStates.hidden;
        Assert.AreEqual(3, trackNotifier.Count);
    }
    );

    MethodUnderTest();
}


Where:
public class TrackInstances<T>
{
    public int Count { get; internal set; }
    public T LastInstance { get;internal set; }
    public Action<T> InitializeAction { get; set; }
}
public static class MockExtend
{
    public static TrackInstances<T> TrackInstances<T>(this Mock<T> mock) where T : class 
    {
        var tracker = new TrackInstances<T>() { Count = 0, LastInstance = null };

        mock.ExpectConstructor();
        // we need to catch the constructor, 
        //  -> as there is a missing API for dynamic return values for constructors 
        //     we will use the MockMethodCalled Event to catch it. 
        mock.MockMethodCalled += new MockMethodCalledEventHandler((sender, e) =>
        {
            if (e.CalledMethodName == ".ctor")
            {
                tracker.LastInstance = (T)sender;
                tracker.Count++;
                if (tracker.InitializeAction != null)
                    tracker.InitializeAction(tracker.LastInstance);
            }
        });
        return tracker;
    }
   
    public static void Do<T>(this Mock<T> mock, string method, params Action<T>[] actions)
    {
        foreach (var action in actions)
        {
            var keepAction = action;
            mock.ExpectAndReturn(method, new DynamicReturnValue((p, o) =>
            {
                keepAction((T)o);
                return null;
            }));
        }
    }
}
answered by eli (5.7k points)
0 votes
Here is a better way:
[TestMethod,VerifyMocks]
public void no_taskbarNotifier_will_be_constructed_if_the_last_instance_of_taskbarnotifer_TaskBarState_not_equal_to_hidden()
{

    var states = new List<State>    {
        new State { Instances = 1, TaskbarState=TaskbarNotifier.TaskbarStates.shown},
        new State { Instances = 1, TaskbarState=TaskbarNotifier.TaskbarStates.hidden},
        new State { Instances = 2, TaskbarState=TaskbarNotifier.TaskbarStates.shown},
        new State { Instances = 2, TaskbarState=TaskbarNotifier.TaskbarStates.shown},
        new State { Instances = 2, TaskbarState=TaskbarNotifier.TaskbarStates.hidden},
        new State { Instances = 3, TaskbarState=TaskbarNotifier.TaskbarStates.hidden},
    };
    int currentState = 0; 


    var mock = MockManager.MockAll<TaskbarNotifier>();
    var trackNotifier = mock.TrackInstances();
    // make sure that TaskbarState is not hidden
    trackNotifier.InitializeAction = instance => instance.TaskbarState = TaskbarNotifier.TaskbarStates.shown;

    var mockApplication = MockManager.Mock<Application>(Constructor.NotMocked);
    mockApplication.DoAlways("DoEvents", e =>
        {
            var state = states[currentState];

            Assert.AreEqual(state.Instances, trackNotifier.Count);
            trackNotifier.LastInstance.TaskbarState = state.TaskbarState;

            currentState++;
        });
 
    MethodUnderTest();
}


Where
public struct State
{
    public int Instances { get; set; }
    public TaskbarNotifier.TaskbarStates TaskbarState { get; set; }
}   
public class TrackInstances<T>
{
    public int Count { get; internal set; }
    public T LastInstance { get;internal set; }
    public Action<T> InitializeAction { get; set; }
}
public static class MockExtend
{
    public static TrackInstances<T> TrackInstances<T>(this Mock<T> mock) where T : class 
    {
        var tracker = new TrackInstances<T>() { Count = 0, LastInstance = null };

        mock.ExpectConstructor();
        // we need to catch the constructor, 
        //  -> as there is a missing API for dynamic return values for constructors 
        //     we will use the MockMethodCalled Event to catch it. 
        mock.MockMethodCalled += new MockMethodCalledEventHandler((sender, e) =>
        {
            if (e.CalledMethodName == ".ctor")
            {
                tracker.LastInstance = (T)sender;
                tracker.Count++;
                if (tracker.InitializeAction != null)
                    tracker.InitializeAction(tracker.LastInstance);
            }
        });
        return tracker;
    }
   
    public static void DoAlways<T>(this Mock<T> mock, string method,  Action<T> action)
    {
        mock.AlwaysReturn(method, new DynamicReturnValue((p, o) =>
        {
            action((T)o);
            return null;
        }));
    }
}
answered by eli (5.7k points)
0 votes
Hi Eli

very interesting code.
But i want also to allow constructors to run . can u extend your code a little more
answered by tolisss (28.8k points)
0 votes
Hi Tolisss

If you want an unmocked constructor use mock.ExpectUnmockedConstructor
so MockExtend.TrackInstances method will be:
public static class MockExtend
{
    public static TrackInstances<T> TrackInstances<T>(this Mock<T> mock) where T : class
    {
        var tracker = new TrackInstances<T>() { Count = 0, LastInstance = null };

==>   mock.ExpectUnmockedConstructor(); // here is the change

        mock.MockMethodCalled += new MockMethodCalledEventHandler((sender, e) =>
        {
            if (e.CalledMethodName == ".ctor")
            {
                tracker.LastInstance = (T)sender;
                tracker.Count++;
                if (tracker.InitializeAction != null)
                    tracker.InitializeAction(tracker.LastInstance);
            }
        });
        return tracker;
    } 
answered by ohad (35.4k points)
...