Insuring order of called methods

11 posts, 0 answers
  1. DavidO
    DavidO avatar
    9 posts
    Member since:
    Jun 2010

    Posted 30 Jun 2010 Link to this post

    I have a simple test that is using MustBeCalled() to insure certain methods are called, but it also needs to know if they are called in the correct order. I thought InSequence() might do this, but it apparently does not, unless I'm not using it correctly. Is there a way to insure order?

    Here is my test:

                ILGenerator gen = Mock.Create<ILGenerator>();
                ISnippetMgr mgr = Mock.Create<ISnippetMgr>();

                MethodInfo get_Item = typeof(Variables).GetProperty("Item", new Type[] { typeof(string) }).GetGetMethod();
                MethodInfo get_AsNumber = typeof(Variable).GetProperty("AsNumber").GetGetMethod();

                Mock.Arrange(() => gen.Emit(OpCodes.Ldarg_1)).MustBeCalled();
                Mock.Arrange(() => gen.Emit(OpCodes.Ldstr, "x")).MustBeCalled();
                Mock.Arrange(() => gen.Emit(OpCodes.Callvirt, get_Item)).MustBeCalled();
                Mock.Arrange(() => gen.Emit(OpCodes.Callvirt, get_AsNumber)).MustBeCalled();

                VarArray v = new VarArray("x", '+');
                v.GenItemCode(mgr, gen);

                Mock.Assert(gen);

    Thanks
  2. Ricky
    Admin
    Ricky avatar
    467 posts

    Posted 01 Jul 2010 Link to this post

    Hi David,

    Thanks that you have asked. By default the ordering is override. In order to apply sequence you need to apply the "InSequece" modifier in your setup.

    I made a post earlier on this , you might like to take a look:
    http://weblogs.asp.net/mehfuzh/archive/2010/05/31/mocking-successive-calls-of-similar-type-via-sequential-mocking.aspx

    Regards,
    Mehfuz


    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  3. DevCraft R3 2016 release webinar banner
  4. DavidO
    DavidO avatar
    9 posts
    Member since:
    Jun 2010

    Posted 01 Jul 2010 Link to this post

    Thank you for your reply.

    In fact, I did see that post on InSequence. However, it appears to be for setting up a sequence of reply values, not asserting that the call was made in a particular order. I have tried it with MustBeCalled but with no luck. The following example is where I am attempting to assert that all of the methods are called and that each is called in the correct order. The problem is, if I reverse the order of any Arrange statements, it does not catch the problem:

    [TestMethod] 
    public void Member_CustomClass_Field_Test2() 
        ILGenerator gen = Mock.Create<ILGenerator>(); 
        ISnippetMgr mgr = Mock.Create<ISnippetMgr>(); 
     
        FieldInfo TestField = typeof(MemberTestClass).GetField("TestField"); 
     
        Mock.Arrange(() => gen.Emit(OpCodes.Ldfld, TestField)).InSequence().MustBeCalled(); 
        Mock.Arrange(() => gen.DeclareLocal(typeof(string))).InSequence().MustBeCalled(); 
        Mock.Arrange(() => gen.Emit(OpCodes.Stloc, Arg.Any<LocalBuilder>())).InSequence().MustBeCalled(); // Dup.1 
        Mock.Arrange(() => gen.Emit(OpCodes.Ldloc, Arg.Any<LocalBuilder>())).InSequence().MustBeCalled(); // Dup.1 
        Mock.Arrange(() => gen.DefineLabel()).InSequence().MustBeCalled(); 
        Mock.Arrange(() => gen.Emit(OpCodes.Brtrue, Arg.Any<Label>())).InSequence().MustBeCalled(); 
        Mock.Arrange(() => gen.Emit(OpCodes.Ldsfld, typeof(string).GetField("Empty"))).InSequence().MustBeCalled(); 
        Mock.Arrange(() => gen.Emit(OpCodes.Stloc, Arg.Any<LocalBuilder>())).InSequence().MustBeCalled(); // Dup.2 
        Mock.Arrange(() => gen.MarkLabel(Arg.Any<Label>())).InSequence().MustBeCalled(); 
        Mock.Arrange(() => gen.Emit(OpCodes.Ldloc, Arg.Any<LocalBuilder>())).InSequence().MustBeCalled(); // Dup.2 
     
        Member m = new Member(null, "TestField", '+') { ObjType = typeof(MemberTestClass) }; 
        Type returnType = m.GenItemCode(mgr, gen, typeof(string)); 
     
        Assert.AreEqual(typeof(string), returnType); 
        Mock.Assert(gen); 
     

  5. Ricky
    Admin
    Ricky avatar
    467 posts

    Posted 06 Jul 2010 Link to this post

    Hi David,
    Thanks again for the detailed example. Here the issue is that you have different types of call and you marked them to be in sequence.

    "InSequence" works for cases where you have multiple setups with similar call and with same arguments, like for example:

    Mock.Arrange(()=> foo.Echo(10)).Returns(1).InSequence();
    Mock.Arrange(()=> foo.Echo(10)).Returns(2).InSequence();
      
    int ret1 = foo.Echo(10);
    int ret2 = foo.Echo(10);
      
    Assert.Equal(1, ret1);
    Assert.Equal(2, ret1);

    Now, if you don't specify the sequential modifier, JustMock will always consider the last setup [Incase of simialr call]:

    Like:
    Mock.Arrange(()=> foo.Echo(10)).Returns(1);
    Mock.Arrange(()=> foo.Echo(10)).Returns(2);
      
    int ret1 = foo.Echo(10);
    int ret2 = foo.Echo(10);
      
    Assert.Equal(2, ret1);
    Assert.Equal(2, ret1);

    Finally, Mock.Assert  verifies if all your required calls have been invoked successfully regardless of the sequence.

    Hope that helps,
    Mehfuz

    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  6. DavidO
    DavidO avatar
    9 posts
    Member since:
    Jun 2010

    Posted 06 Jul 2010 Link to this post

    Thank you. Yes, I realize that is the correct use of InSequence(). So does JustMock provide any facility to verify the correct order of method calls? What I've ended up doing is crude and difficult to maintain, but it works. This is what it looks like:

    [TestMethod] 
    public void Member_CustomClass_Field_Test() 
        ILGenerator gen = Mock.Create<ILGenerator>(); 
        ISnippetMgr mgr = Mock.Create<ISnippetMgr>(); 
     
        FieldInfo TestField = typeof(MemberTestClass).GetField("TestField"); 
     
        int track = 0
     
        Mock.Arrange(() => gen.Emit(OpCodes.Ldfld, TestField)).DoInstead(() => { Assert.AreEqual(1, ++track); }); 
        Mock.Arrange(() => gen.DeclareLocal(typeof(string))).DoInstead(() => { Assert.AreEqual(2, ++track); }); 
      //Mock.Arrange(() => gen.Emit(OpCodes.Stloc, Arg.Any<LocalBuilder>())).DoInstead(() => { Assert.AreEqual(3, ++track); }); // Dup. 
      //Mock.Arrange(() => gen.Emit(OpCodes.Ldloc, Arg.Any<LocalBuilder>())).DoInstead(() => { Assert.AreEqual(4, ++track); }); // Dup. 
        Mock.Arrange(() => gen.DefineLabel()).DoInstead(() => { Assert.AreEqual(5, ++track); }); 
        Mock.Arrange(() => gen.Emit(OpCodes.Brtrue, Arg.Any<Label>())).DoInstead(() => { Assert.AreEqual(6, ++track); }); 
        Mock.Arrange(() => gen.Emit(OpCodes.Ldsfld, typeof(string).GetField("Empty"))).DoInstead(() => { Assert.AreEqual(7, ++track); }); 
        Mock.Arrange(() => gen.Emit(OpCodes.Stloc, Arg.Any<LocalBuilder>())).DoInstead(() => { track++; Assert.IsTrue(track == 8 || track == 3); }); 
        Mock.Arrange(() => gen.MarkLabel(Arg.Any<Label>())).DoInstead(() => { Assert.AreEqual(9, ++track); }); 
        Mock.Arrange(() => gen.Emit(OpCodes.Ldloc, Arg.Any<LocalBuilder>())).DoInstead(() => { track++; Assert.IsTrue(track == 10 || track == 4); }); 
     
        Member m = new Member(null, "TestField", '+') { ObjType = typeof(MemberTestClass) }; 
        Type returnType = m.GenItemCode(mgr, gen, typeof(string)); 
     
        Assert.AreEqual(typeof(string), returnType); 
        Assert.IsTrue(track == 10); 
     

    It would be really helpful if there was a built-in mechanism in the JustMock framework. If there isn't, consider this a feature request.

    Thanks!
  7. Ricky
    Admin
    Ricky avatar
    467 posts

    Posted 08 Jul 2010 Link to this post

    Hi David,

    It’s nice to hear that you made it work for you. Also, I am putting the feature mentioned by you into our backlog with the following title:
     
    Support of extending InSequece() modifier to ensure the correct order of any method call through Mock.Assert() .
     
    Hopefully, it will be available in one of the upcoming builds.

    Kind Regards,
    Mehfuz


    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  8. DavidO
    DavidO avatar
    9 posts
    Member since:
    Jun 2010

    Posted 08 Jul 2010 Link to this post

    That is terrific! Thank you. JustMock is a great product already. I'm excited to see it get even better.
  9. David Allen
    David Allen avatar
    6 posts
    Member since:
    Mar 2009

    Posted 06 Apr 2013 Link to this post

    Is there any progress on this? It is a very common scenario. I can create a hand-made mock to do this, but that means I am not using JustMock at all in this case.

    I need to ensure that certain methods are called in a certain order. Not just that they are called.
  10. Kaloyan
    Admin
    Kaloyan avatar
    872 posts

    Posted 09 Apr 2013 Link to this post

    Hello David Allen,

    To achieve this, you can use "InOrder()", like this:
    public interface IOrdered
    {
        void OrderedOnClassInitialize();
        void OrderedOnTestInitialize();
        void OrderedOnTestMethod();
    }
     
    [TestClass]
    public class OrderedTests
    {
        [TestMethod]
        public void ShouldAssertInOrderedCalls()
        {
            var orderedMock = Mock.Create<IOrdered>();
     
            Mock.Arrange(() => orderedMock.OrderedOnClassInitialize()).InOrder();
            Mock.Arrange(() => orderedMock.OrderedOnTestInitialize()).InOrder();
            Mock.Arrange(() => orderedMock.OrderedOnTestMethod()).InOrder();
     
            orderedMock.OrderedOnClassInitialize();
            orderedMock.OrderedOnTestInitialize();
            orderedMock.OrderedOnTestMethod();
     
            Mock.Assert(orderedMock);
        }
    }
    Note that, if you change the order of the method calls or the arrangements, the test will fail.

    I hope this helps.

    Kind regards,
    Kaloyan
    the Telerik team
    Share what you think about JustTrace & JustMock with us, so we can become even better! You can use the built-in feedback tool inside JustTrace, our forums, or our JustTrace or JustMock portals.
  11. David Allen
    David Allen avatar
    6 posts
    Member since:
    Mar 2009

    Posted 09 Apr 2013 Link to this post

    Thanks. The "InOrder" method in Mock.Arrange works just fine.  I was looking for something like that in the Mock.Assert method instead. 
    Using the technique you suggested, I must order my test like this

    //Arrange (initial conditions)
    // setup expected results (ordering)
    // Act
    // Assert

    What I would prefer is 
    //Arrange
    //Act
    // Assert (expected results in order)

    But using InOrder in Mock.Arrange is perfectly workable.
  12. Kaloyan
    Admin
    Kaloyan avatar
    872 posts

    Posted 09 Apr 2013 Link to this post

    Hello David Allen,

    I am glad, this works for you.

    However, thank you for the feedback and the great idea. We will definitely take it into consideration.

    Regards,
    Kaloyan
    the Telerik team
    Share what you think about JustTrace & JustMock with us, so we can become even better! You can use the built-in feedback tool inside JustTrace, our forums, or our JustTrace or JustMock portals.
Back to Top
DevCraft R3 2016 release webinar banner