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.
GetTypeInfo()
. You're right that extension/static methods are best avoided but in this case I don't have much choice as it's a built-in one I have to use to inspect type information in .NET Core. – Tagcpublic class MockBehaviour : IMofichanBehaviour { ... }
– Nkosi