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

How-to write tests for extension methods without Typemock

Ok, I’m not a happy owner of Typemock, hence I can’t use it to mock extension methods.

I will show you two really simple workarrounds for achieving this.

I have some simple extension methods that extends IQueryable. One of the extensions is responsible for checking if a certain username allready is taken.
The extension method

public static bool UsernameIsTaken(this IQueryable<UserAccount> userAccounts, string username)
{
    return
        userAccounts.Where(
            u =>
            u.Username.Equals(username, StringComparison.InvariantCultureIgnoreCase)).Count() > 0;
}

As I’m using the Moq-framework for setting up my fakes (in this case stub, see earlier post) I will get an exception.

The test as I want it (which doesn’t work) looks like this

[TestMethod]
public void Validate_TakenUsername_GivesViolation()
{
    var userAccount = UserAccountFactoryForTests.CreateValidUserAccount();
    var userAccountStoreStub = Fake.Stub.New<IQueryable<UserAccount>>();
    Fake.Stub.Returns(userAccountStoreStub, stub => stub.UsernameIsTaken(userAccount.Username), true);

    var validator = new NewUserAccountValidator(userAccountStoreStub);
    var validationResult = validator.Validate(userAccount);

    Assert.AreEqual(TimeTracking.Domain.Resources.UserAccountValidationMessages.UsernameIsAllreadyTaken, validationResult.GetViolationsByMembername("Username")[0].ErrorMessage);
}

This stub is fairly simple to replace manually. All I need is a generic List of UserAccount that contains an instance of an useraccount that has the same username as the username I’m validating.

Solution 1 – Setup a generic list and pass it as IQueryable

[TestMethod]
public void Validate_TakenUsername_GivesViolation()
{
    var userAccount = UserAccountFactoryForTests.CreateValidUserAccount();
    var userAccountStoreStub = new List<UserAccount>
                                   {
                                       UserAccountFactoryForTests.CreateValidUserAccount()
                                   }.AsQueryable();
    
    var validator = new NewUserAccountValidator(userAccountStoreStub);
    var validationResult = validator.Validate(userAccount);

    Assert.AreEqual(TimeTracking.Domain.Resources.UserAccountValidationMessages.UsernameIsAllreadyTaken, validationResult.GetViolationsByMembername("Username")[0].ErrorMessage);
}

This time I was lucky, since the extension method was on the IQueryable, but what if it was something that is totally custom? Just let the extension method consume something that you can stub. In this case, e.g., a Func (see Daniel Cazzulino’s blog).

Solution 2 – Let the extension method consume something you can stub

public static class UserAccountQueries
{
    public static Func<IQueryable<UserAccount>, string, bool> userNameIsTaken = (userAccounts, username) =>
        userAccounts.Where(
                u =>
                u.Username.Equals(username, StringComparison.InvariantCultureIgnoreCase)).Count() > 0;

    public static bool UsernameIsTaken(this IQueryable<UserAccount> userAccounts, string username)
    {
        return userNameIsTaken(userAccounts, username);
    }
}
[TestMethod]
public void Validate_TakenUsername_GivesViolation()
{
    var userAccount = UserAccountFactoryForTests.CreateValidUserAccount();
    UserAccountQueries.userNameIsTaken = (stub, username) => true;

    var validator = new NewUserAccountValidator(new List<UserAccount>().AsQueryable());
    var validationResult = validator.Validate(userAccount);

    Assert.AreEqual(TimeTracking.Domain.Resources.UserAccountValidationMessages.UsernameIsAllreadyTaken, validationResult.GetViolationsByMembername("Username")[0].ErrorMessage);
}

In my scenario I used solution 1, but in the future I will probably refactor away my code from the extension methods.

//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