dimanche 13 novembre 2016

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.

Aucun commentaire:

Enregistrer un commentaire