Randy Minder
Randy Minder

Reputation: 48402

How to Mock this using MSTest and Moq

I'm just learning how to use Moq, with MSTest. I have the following method I want to test, in an existing applicaton:

/// <summary>
/// Return the marker equipment Id value give a coater equipment Id value.
/// </summary>
/// <param name="coaterEquipmentId">The target coater</param>
/// <returns>The marker equipment Id value</returns>
internal static string GetMarkerEquipmentId(string coaterEquipmentId)
{
    return CicApplication.CoaterInformationCache
        .Where(row => row.CoaterEquipmentId == coaterEquipmentId)
        .Select(row => row.MarkerEquipmentId)
        .First();
}

The CicApplication object is a 'global' object with a property named CoaterInformationCache, which is a List of CoaterInformation classes.

I assume I will need to mock the CicApplication.CoaterInformationCache somehow, and I probably need to pass this method an interface containing the list of CoaterInformation classes, instead of accessing the list via a global object that only contains values at runtime?

Thanks very much

Upvotes: 1

Views: 2155

Answers (1)

Scott Wegner
Scott Wegner

Reputation: 7483

Globals / statics are a bane for unit testability. To make this testable, you're correct in that you should eliminate the CicApplication global. You can create an interface, i.e. ICicApplication with the same public API, and pass an instance into your application code.

public interface ICicApplication
{
    public List<CoaterInformation> CoaterInformationCache { get; }
}

public DefaultCicApplication : ICicApplication
{
    public List<CoaterInformation> CoaterInformationCache
    {
        // Either use this class as an adapter for the static API, or move
        // the logic here.
        get { return CicApplication.CoaterInformationCache; }
    }
}

Since this is a static method, you could pass it as a method argument, otherwise, convert the static method to an instance method an initialize a ICicApplication field on the object (perhaps pass an instance into the constructor).

Then, when you set up your unit test, you can pass in a mock instance set up with Moq:

Mock<ICicApplication> appMock = new Mock<ICicApplication>();
appMock
    .SetupGet(ca => ca.CoaterInformationCache)
    .Returns(new List<CoaterInformation> { ... });

Upvotes: 2

Related Questions