Tagc Tagc - 20 days ago 14
C# Question

Is it possible to mock the "type name" of a mock in C# using Moq?

I'm developing a chatbot in C# (based on .NET Core) that has modular behaviours. One of the behaviours I want to develop is an "admin" module that (among other functions) should allow admins to dynamically enable or disable other behaviours by name.

I want the admin module to determine the name of a behaviour by inspecting its type info and doing something like:

var name = behaviour.GetType().GetTypeInfo().Name.Replace("Behaviour", string.Empty).ToLowerInvariant();


In a BDD specification I'm writing first, I'm trying to set up a "behaviour chain" consisting of the admin module (system under test) and a mock behaviour. The tests involve sending commands that should cause the admin module to enable or disable the mock behaviour.

This is what I've done so far:

public BehaviourIsEnabled() : base("Admin requests that a behaviour is enabled")
{
var mockTypeInfo = new Mock<TypeInfo>();
mockTypeInfo.SetupGet(it => it.Name).Returns("MockBehaviour");

var mockType = new Mock<Type>();
mockType.Setup(it => it.GetTypeInfo()).Returns(mockTypeInfo.Object);

// TODO: make mock behaviour respond to "foo"
var mockBehaviour = new Mock<IMofichanBehaviour>();
mockBehaviour.Setup(b => b.GetType()).Returns(mockType.Object);

this.Given(s => s.Given_Mofichan_is_configured_with_behaviour("administration"), AddBehaviourTemplate)
.Given(s => s.Given_Mofichan_is_configured_with_behaviour(mockBehaviour.Object),
"Given Mofichan is configured with a mock behaviour")
.And(s => s.Given_Mofichan_is_running())
.When(s => s.When_I_request_that_a_behaviour_is_enabled("mock"))
.And(s => s.When_Mofichan_receives_a_message(this.JohnSmithUser, "foo"))
.Then(s => s.Then_the_mock_behaviour_should_have_been_triggered())
.TearDownWith(s => s.TearDown());
}


The problem when I run this is that
GetTypeInfo()
is an extension method on
Type
, so Moq throws the exception:


Expression references a method that does not belong to the mocked
object: it => it.GetTypeInfo()


An an alternative, I could just add a
Name
property to
IMofichanBehaviour
, but I don't like the idea of adding arbitrary methods/properties to production code that's only really there for the benefit of test code.

Answer

Keep it simple with a fake class that satisfies what it being mocked.

public class MockBehaviour : IMofichanBehaviour { ... }

And test would then look like

public BehaviourIsEnabled() : base("Admin requests that a behaviour is enabled") {

    // TODO: make mock behaviour respond to "foo"
    var mockBehaviour = new MockBehaviour();


    this.Given(s => s.Given_Mofichan_is_configured_with_behaviour("administration"), AddBehaviourTemplate)
        .Given(s => s.Given_Mofichan_is_configured_with_behaviour(mockBehaviour),
                "Given Mofichan is configured with a mock behaviour")
            .And(s => s.Given_Mofichan_is_running())
        .When(s => s.When_I_request_that_a_behaviour_is_enabled("mock"))
            .And(s => s.When_Mofichan_receives_a_message(this.JohnSmithUser, "foo"))
        .Then(s => s.Then_the_mock_behaviour_should_have_been_triggered())
        .TearDownWith(s => s.TearDown());
}
Comments