Moq vs Typemock – It.IsAny & It.Is

I kind of like the It.IsAny syntax and It.IsAny(validation expression) syntax of Moq. So now when I’m in the process of switching to Typemock I really was looking for this kind of API.

I have put together some simple samples to show the difference.

The difference in the APIs

#1

[Test]
public void VerifyCallWithExplicitArguments_WhenSameInstanceArgs_VerifiesOk()
{
    var args = new MyArgsWithoutEquals();
    var fake = new Mock<MyClassUnderTest>();

    var invoker = new Invoker(fake.Object);
    invoker.Invoke(args);

    fake.Verify(f => f.MyMethod(args));
}
[Test, Isolated]
public void VerifyCallWithExplicitArguments_WhenSameInstanceArgs_VerifiesOk()
{
    var args = new MyArgsWithoutEquals();
    var fake = Isolate.Fake.Instance<MyClassUnderTest>();

    var invoker = new Invoker(fake);
    invoker.Invoke(args);

    Isolate.Verify.WasCalledWithExactArguments(
        () => fake.MyMethod(args));
}

#2

[Test]
public void VerifyCallWithExplicitArguments_WhenOtherInstanceArgs_ThrowsMockException()
{
    var args = new MyArgsWithoutEquals();
    var argsOther = new MyArgsWithoutEquals();
    var fake = new Mock<MyClassUnderTest>();

    var invoker = new Invoker(fake.Object);
    invoker.Invoke(argsOther);

    Assert.Throws<MockException>(
        () => fake.Verify(f => f.MyMethod(args)));
}
[Test, Isolated]
public void VerifyCallWithExplicitArguments_WhenOtherInstanceArgs_ThrowsMockException()
{
    var args = new MyArgsWithoutEquals();
    var argsOther = new MyArgsWithoutEquals();
    var fake = Isolate.Fake.Instance<MyClassUnderTest>();

    var invoker = new Invoker(fake);
    invoker.Invoke(argsOther);

    Assert.Throws<VerifyException>(
        () => Isolate.Verify.WasCalledWithExactArguments(
            () => fake.MyMethod(args)));
}

#3

[Test]
public void VerifyCallWithExplicitArgumentsAndValues_WhenOtherInstanceArgsWithSameValues_VerifiesOk()
{
    var args = new MyArgsWithoutEquals { Id = 1 };
    var argsOther = new MyArgsWithoutEquals { Id = 1 };
    var fake = new Mock<MyClassUnderTest>();

    var invoker = new Invoker(fake.Object);
    invoker.Invoke(argsOther);

    fake.Verify(f => f.MyMethod(It.Is<MyArgsWithoutEquals>(a => a.Id == args.Id)));
}
[Test, Isolated]
public void VerifyCallWithExplicitArgumentsAndValues_WhenOtherInstanceArgsWithSameValues_VerifiesOk()
{
    var args = new MyArgsWithoutEquals { Id = 1 };
    var argsOther = new MyArgsWithoutEquals { Id = 1 };
    var fake = Isolate.Fake.Instance<MyClassUnderTest>();

    var invoker = new Invoker(fake);
    invoker.Invoke(argsOther);

    Isolate.Verify.WasCalledWithArguments(
        () => fake.MyMethod(args)).Matching(a => ((MyArgsWithoutEquals)a[0]).Id == args.Id);
}

#4

[Test]
public void VerifyCallWithExplicitArguments_WhenOtherInstanceArgsWithEqualsImplementation_VerifiesOk()
{
    var args = new MyArgsWithEquals();
    var argsOther = new MyArgsWithEquals();
    var fake = new Mock<MyClassUnderTest>();

    var invoker = new Invoker(fake.Object);
    invoker.Invoke(argsOther);

    fake.Verify(f => f.MyMethod(args));
}
[Test, Isolated]
public void VerifyCallWithExplicitArguments_WhenOtherInstanceArgsWithEqualsImplementation_VerifiesOk()
{
    var args = new MyArgsWithEquals();
    var argsOther = new MyArgsWithEquals();
    var fake = Isolate.Fake.Instance<MyClassUnderTest>();

    var invoker = new Invoker(fake);
    invoker.Invoke(argsOther);

    Isolate.Verify.WasCalledWithExactArguments(
        () => fake.MyMethod(args));
}

#5

[Test]
public void VerifyCallWithAnyArguments_WhenInstanceOfCorrectType_VerifiesOk()
{
    var args = new MyArgsWithoutEquals();
    var fake = new Mock<MyClassUnderTest>();

    var invoker = new Invoker(fake.Object);
    invoker.Invoke(args);

    fake.Verify(f => f.MyMethod(It.IsAny<MyArgsWithoutEquals>()));
}
[Test, Isolated]
public void VerifyCallWithAnyArguments_WhenInstanceOfCorrectType_VerifiesOk()
{
    var args = new MyArgsWithoutEquals();
    var fake = Isolate.Fake.Instance<MyClassUnderTest>();
            
    var invoker = new Invoker(fake);
    invoker.Invoke(args);

    Isolate.Verify.WasCalledWithAnyArguments(() => fake.MyMethod(null));
}

Test duration

I also spotted something else. The difference in duration of the tests. Even though this isn’t a realistic scenario, since I only have five tests, I thinkt it’s kind of fun to see. It would be interesting to swap in a real scenario where there’s alot of faking going on.
Moq vs Typemock - Test duration

When doing these tests I was consuming:

  • Moq v4.0.10501.6 (what’s with all these decimals. I just wan’t to be able to determine older/never)
  • Typemock v6.0.3.0

I also tested to disable Typemock and to run the Moq test alone. The result was the same.

Download the code here

The conclusions

Conclusion #1
Regarding to the It.IsAny and It.Is(validation expression), the conclusion is that the only API member I’m missing, is the It.IsAny. Why? Because I really don’t like the way I have to pass null to WithAnyArguments, in Typemock. I really hope they implement something similar. And if they have, please correct me.

Conclusion #2
I also would like Typemock to provide me a solution where I don’t have to verify against an object[] as in code example #3 above.

Conclusion #3
I like the way Typemock uses “Fakes” instead of “Mocks”. This since Fakes covers both Stubs and Mocks, while the Moq framework lets Mock represent both Stubs and Mocks, which is somewhat confusing.

So, so far I’m happy with the invested money in Typemock.

//Daniel

Faking API for stubs and mocks

Just for fun I started to build my own API for taking care of stubbing and mocking while writing my tests. It wasn’t all for fun, since I didn’t like the API of the Moq-framework (read earlier writings about this) I thought that I could wrap Moq in my own API. Since I’m not consuming all the functionality of the Moq-framework, I will get a more slim API that doesn’t tangle stubs and mocks. It will also make it possible for me to switch (why I would like this I really don’t know) for another framework than Moq; or actually build my own instead of just a wrapper.

The result? Well as I see it it all start with the intent of faking something (use a stand-in); either as a simple stub or a mock. And the stub and mock should have different configuration API.

The result so far (since I add functionality when I need it)

var newUserAccount = UserAccountFactoryForTests.CreateValidUserAccount();
var entityStoreMock = Fake<IEntityStore>.Mock();
var componentContainerStub = Fake<IoCContainer>.Stub()
    .Returns(c => c.Resolve<IEntityStore>(), entityStoreMock.MockedObject);
var service = new SecurityService { ServicesIoCContainer = componentContainerStub.StubbedObject };

The code can be downloaded from here.

//Daniel

The Moq, mockingframework, and the tangling of Stubs and Mocks

When I need the powers of a Faking-framework I use the Moq-framework, which I use when I feel that it is to much work for creating a manual Fake (which I only do with stubs). There’s one thing that I really don’t like with Moq, the tangling of Mocks and Stubs. I like to see them as follows:

Fakes

  • Stubs (is used to make interaction work and to return or throw exceptions etc.)
  • Mocks (is used to assert against by putting demands/expectations on the interaction)
  • This is why I wrote “Faking-framework” above. A stub is a fake and a mock is a fake but a mock is not a stub and a stub is not a mock. Glad that we sorted that out!

    Don’t get me wrong here, I like the Moq-framework, but what I would like to see in it is a separation of stubs and mocks. The API should let you clearly create a stub or a mock. You shouldn’t be able to turn a stub into a mock. When creating the stub, a class named Mock is confusing and missleading hence should not be used.

    Look at the following simple test. I have a shoppingcart for a customer and the cart uses a pricelocator to lookup the prices of the products that I’m adding. The price is determined by looking at the customer, the product and the quantity. In the test I create a stub for my pricelocator, so that I’m sure of the prices it will return. I stub the pricelocator so that the test can query it for two different products for the same customer. Then I add two items to the shoppingcart, which will use the pricelocator when I invoke the GetTotal-function on my shoppingcart.

    The test

    [TestClass]
    public class ShoppingCartTests
    {
        [TestMethod]
        public void GetTotal_TwoValidShoppingCartItems_GivesTotal()
        {
            const string customerNo = "2010-1";
            var item1 = new { CustomerNo = customerNo, ProductNo = "P01-01-00001", Quantity = 2, Result = 101.50M };
            var item2 = new { CustomerNo = customerNo, ProductNo = "P01-01-00002", Quantity = 3, Result = 99.75M };
    
            var expectedTotal = item1.Result + item2.Result;
            var priceLocatorStub = GetPriceLocatorStub(item1, item2);
    
            var shoppingCart = new ShoppingCart(customerNo) { PriceLocator = priceLocatorStub };
            shoppingCart.AddProduct(item1.ProductNo, item1.Quantity);
            shoppingCart.AddProduct(item2.ProductNo, item2.Quantity);
            var actualTotal = shoppingCart.GetTotal();
    
            Assert.AreEqual(expectedTotal, actualTotal);
        }
    
        private static IPriceLocator GetPriceLocatorStub(params object[] items)
        {
            var priceLocatorStub = new Moq.Mock<IPriceLocator>();
    
            foreach (var item in items)
            {
                var tmp = TypeCaster.CastAnonymous(item, new { CustomerNo = "", ProductNo = "", Quantity = 0, Result = 0M });
    
                priceLocatorStub
                    .Setup(pl => pl.LookupPrice(
                                     tmp.CustomerNo,
                                     tmp.ProductNo,
                                     tmp.Quantity)).Returns(tmp.Result);
            }
    
            return priceLocatorStub.Object;
        }
    }
    

    What if I add a expectation to my stub? It is possible, but should it be? Yes it’s possible. With the little change of adding “.AtMost(0)” below, I have created an mock and totally changed the semantics, hence the Assert should change to, but that’s not the point in this blog post. The point is that I think the Moq guys should keep the mocks and stubs API’s sepparated, so when I create a stub I can’t add expectations.

    priceLocatorStub
        .Setup(pl => pl.LookupPrice(
                         tmp.CustomerNo,
                         tmp.ProductNo,
                         tmp.Quantity)).Returns(tmp.Result).AtMost(0);
    

    The changes I want are:

    Instead of:

    var stub = new Mock();
    

    I want:

    var stub = new Stub();
    

    and not being able to add e.g. AtMost-expectations to the Stub.

    Even if this change will not come, I will continue to use the Moq-framework.

    To finnish of, I would like to point out that I think this missuse of the terms mocks and mocking is common amongst developers; who gladly uses variablenames like “*Mock” when they actually are creating a stub; who frequently speaks in terms of mocks, when they actually are using stubs.

    The complete sourcecode can be downloaded from here.

    //Daniel