This is a migrated thread and some comments may be shown as answers.

Insuring order of called methods

10 Answers 192 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
DavidO
Top achievements
Rank 1
DavidO asked on 30 Jun 2010, 05:39 PM
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

10 Answers, 1 is accepted

Sort by
0
Ricky
Telerik team
answered on 01 Jul 2010, 09:24 AM
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
0
DavidO
Top achievements
Rank 1
answered on 01 Jul 2010, 06:07 PM
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); 
 

0
Ricky
Telerik team
answered on 06 Jul 2010, 04:09 PM

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
0
DavidO
Top achievements
Rank 1
answered on 06 Jul 2010, 05:37 PM
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!
0
Ricky
Telerik team
answered on 08 Jul 2010, 03:24 PM

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
0
DavidO
Top achievements
Rank 1
answered on 08 Jul 2010, 04:58 PM
That is terrific! Thank you. JustMock is a great product already. I'm excited to see it get even better.
0
David Allen
Top achievements
Rank 1
answered on 06 Apr 2013, 08:28 PM
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.
0
Kaloyan
Telerik team
answered on 09 Apr 2013, 08:35 AM
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.
0
David Allen
Top achievements
Rank 1
answered on 09 Apr 2013, 12:42 PM
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.
0
Kaloyan
Telerik team
answered on 09 Apr 2013, 01:06 PM
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.
Tags
General Discussions
Asked by
DavidO
Top achievements
Rank 1
Answers by
Ricky
Telerik team
DavidO
Top achievements
Rank 1
David Allen
Top achievements
Rank 1
Kaloyan
Telerik team
Share this question
or