Here is a first look at the upcoming DynMock dynamic mocking & stubbing framework syntax. We will show more functionality in the forums as they are ready. We'll keep you posted.

Mocking and stubbing

Arrange is a static class that arranges the mocking & stubbing. Arrange.Mock<T> defines the creation of a mock or stub.

Defining rules

Arrange.Call defines the definition or rules for a member. The MustReturn<T>(this,T) extension says that any call to a method must return a certain value.

Defining constraints

CantHappen() creates a restrictive constraint that will throw an exception of the member being defined is ever called. We also have CanHappenOnce() where the member can be called 0-1 times, CanBeCalled(int num) allows you to allow a member to be called 0-num times. MustHappenOnce() is a restrictive constraint that will cause an exception from the object destructor if the member was not called exactly once. MustBeCalled(int num) will cause an exception from the object destructor if the member was not called exactly num times.

using Microsoft.VisualStudio.TestTools.UnitTesting;
using SysSurge.DynMock.Core;

public interface IWarehouse
{
    int GetStockCount();
    IProduct GetBestSeller();
    void Foo();
}

public class Warehouse : IWarehouse
{
    private readonly IProduct _product;

    public int GetStockCount()
    {
        Foo();
        return 1000;
    }

    public void Foo()
    {
        // ...
    }

    public IProduct GetBestSeller()
    {
        return _product;
    }

    public Warehouse(IProduct product)
    {
        _product = product;
    }
}
namespace SysSurge.DynMock.Tests
{
    [TestClass]
    public class GenericTests
    { 
        [TestMethod]
        public void ActionMockTest1()
        {
            var warehouse = Arrange.Mock<IWarehouse>();
            Arrange.Call(() => warehouse.GetStockCount()).MustReturn(1);
            Arrange.Call(() => warehouse.Foo()).CantHappen();
            Assert.AreEqual(1, warehouse.GetStockCount());
        }
    }
}

Strict vs Loose Semantics

DynMock support both Strict & Loose Semantics, Loose is by default. .NET is Strongly Typed and its default behaviour is to throw RuntimeBinderException's if an undefined member is called at runtime. Mocking frameworks, on the other hand, sometime support what's called "Loose Semantics", this means that calling undefined members will return an empty value; usually are 0 for numbers and NULL for objects, and without throwing an exception.

Below is an example of the DynMock syntax works when it comes to behaviour semantics.

[TestMethod]
public void UndefinedMember_StrictSemantics_ExpectException()
{
    var warehouse = Arrange.Mock<IWarehouse>(BehaviourSemantics.Strict);

    var caughtException = false;
    try
    {
        var stockCount = warehouse.GetStockCount();
    }
    catch (RuntimeBinderException)
    {
        caughtException = true;
    }

    Assert.IsTrue(caughtException);
}

[TestMethod]
public void CallUndefinedMember_LooseSemantics()
{
    var warehouse = Arrange.Mock<IWarehouse>();
    var stockCount = warehouse.GetStockCount();
    Assert.AreEqual(0, stockCount);
}
Published • Modified
Add your own reply