bitblack / moq

Automatically exported from code.google.com/p/moq
Other
0 stars 0 forks source link

MockSequence on same moq not working properly? #291

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
    public interface IDatabase
    {
        void BeginTransaction();

        void CommitTransaction();

        void RollbackTransaction();

        void Save(int number);
    }

    public class DataAccess
    {
        private readonly IDatabase database;

        public DataAccess(IDatabase database)
        {
            this.database = database;
        }

        public void CorrectSave(int number)
        {
            try
            {
                this.database.BeginTransaction();

                this.database.Save(number);

                this.database.CommitTransaction();
            }
            catch (InvalidOperationException)
            {
                this.database.RollbackTransaction();
            }
        }

        public void IncorrectSave(int number)
        {
            try
            {
                this.database.Save(number);

                this.database.BeginTransaction();

                this.database.CommitTransaction();
            }
            catch (InvalidOperationException)
            {
                this.database.RollbackTransaction();
            }
        }
    }   

 public class DataAccessTest
    {
        private readonly Mock<IDatabase> database;
        private readonly DataAccess testee;

        public DataAccessTest()
        {
            this.database = new Mock<IDatabase>(MockBehavior.Strict);

            this.testee = new DataAccess(this.database.Object);
        }

        [Fact]
        public void CorrectSave()
        {
            var sequence = new MockSequence();

            this.database.InSequence(sequence).Setup(d => d.BeginTransaction());
            this.database.InSequence(sequence).Setup(d => d.Save(It.IsAny<int>()));
            this.database.InSequence(sequence).Setup(d => d.CommitTransaction());

            Assert.ShouldNotThrow(() => this.testee.CorrectSave(1));
        }

        [Fact]
        public void IncorrectSave()
        {
            var sequence = new MockSequence();

            this.database.InSequence(sequence).Setup(d => d.BeginTransaction());
            this.database.InSequence(sequence).Setup(d => d.Save(It.IsAny<int>()));
            this.database.InSequence(sequence).Setup(d => d.CommitTransaction());

            Assert.Throws<MockException>(() => this.testee.IncorrectSave(1));
        }
    }

Original issue reported on code.google.com by lobomina...@gmx.ch on 27 Oct 2010 at 9:18

GoogleCodeExporter commented 8 years ago
I also noticed the same problem, here is another test case (a slightly modified 
version of the original sequence test cases). I am really looking forward to 
this feature being fixed.

      [TestMethod]
      public void ThisShouldWork() {
         var a = new Mock<IFoo>(MockBehavior.Strict);

         MockSequence t = new MockSequence();
         a.InSequence(t).Setup(x => x.M(100)).Returns(101);
         a.InSequence(t).Setup(x => x.M(200)).Returns(201);

         a.Object.M(100);
         a.Object.M(200);
      }

      [TestMethod]
      public void ThisShouldNotWork() {
         var a = new Mock<IFoo>(MockBehavior.Strict);

         MockSequence t = new MockSequence();
         a.InSequence(t).Setup(x => x.M(100)).Returns(101);
         a.InSequence(t).Setup(x => x.N(100)).Returns(201);

         a.Object.N(100);
         a.Object.M(100);
      }

      public interface IFoo {
         int M(int p);
         int N(int p);
      }

Original comment by daniel.b...@gmail.com on 20 Nov 2010 at 5:21

GoogleCodeExporter commented 8 years ago
I fixed this issue by changing one method 'Matches' in 'MethodCall' class 
(MethodCall.cs)
from:
public virtual bool Matches(ICallContext call)
        {
            if (condition != null && !condition())
            {
                return false;
            }

            var parameters = call.Method.GetParameters();
            var args = new List<object>();
            for (int i = 0; i < parameters.Length; i++)
            {
                if (!parameters[i].IsOutArgument())
                {
                    args.Add(call.Arguments[i]);
                }
            }

            if (argumentMatchers.Count == args.Count && this.IsEqualMethodOrOverride(call))
            {
                for (int i = 0; i < argumentMatchers.Count; i++)
                {
                    if (!argumentMatchers[i].Matches(args[i]))
                    {
                        return false;
                    }
                }

                return true;
            }

            return false;
        }
to:
public virtual bool Matches(ICallContext call)
        {
            var parameters = call.Method.GetParameters();
            var args = new List<object>();
            for (int i = 0; i < parameters.Length; i++)
            {
                if (!parameters[i].IsOutArgument())
                {
                    args.Add(call.Arguments[i]);
                }
            }

            if (argumentMatchers.Count == args.Count && this.IsEqualMethodOrOverride(call))
            {
                for (int i = 0; i < argumentMatchers.Count; i++)
                {
                    if (!argumentMatchers[i].Matches(args[i]))
                    {
                        return false;
                    }
                }

                return condition == null || condition(); // <<replacement>> should check condition only in case of all argumets are matched
            }

            return false;
        }

The problem was in condition() implementation of MockSequence class which for 
first setup check increase sequence counter.

PS All tests are successfully passed 

Original comment by stimpi...@gmail.com on 16 May 2011 at 12:43

GoogleCodeExporter commented 8 years ago
I also stumbled on this issue, the fix seems easy, so +1 !

Original comment by julian.l...@gmail.com on 13 Feb 2012 at 9:18

GoogleCodeExporter commented 8 years ago
Any news on this issue?

A poor man's approach to verifying the order in which mocks are called, is to 
maintain your own counter with callbacks, and Assert the value of the counter 
variable:

http://stackoverflow.com/a/10609506/2972

Original comment by m...@milkshakesoftware.com on 14 Nov 2012 at 9:03

GoogleCodeExporter commented 8 years ago
Pull request @ github.com/Moq/moq4 ?

Original comment by dan...@cazzulino.com on 14 Nov 2012 at 9:55

GoogleCodeExporter commented 8 years ago
Hi,

I have coded together a new feature proposal for sequential verification for 
Moq at: https://github.com/grzesiek-galezowski/moq4. This proposal includes 
sequential verification that works with loose mocks and also three types of 
sequence behaviors. The changes need some review (does it work properly? Is it 
needed? Is something missing?), so anybody reading this, please test this 
implementation and add comments to https://github.com/Moq/moq4/issues/21. The 
examples on how to use the proposed functionality can be found at: 
https://github.com/grzesiek-galezowski/moq4/blob/dev/UnitTests/VerifyInSequenceF
ixture.cs

Best regards,
grzesiek gałęzowski

Original comment by grzesiek...@gmail.com on 27 Dec 2012 at 10:16

GoogleCodeExporter commented 8 years ago
Is this STILL not working? A YEAR after a suggested solution was posted?

Original comment by sean.hed...@gmail.com on 7 Jan 2014 at 9:18