Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Moq, System.InvalidCastException : Unable to cast object of type 'Castle.Proxies.ObjectProxy' to type

Can someone help me to fix this error message please? I don't understand why the cast doesn't work:

Message: System.InvalidCastException : Unable to cast object of type 'Castle.Proxies.ObjectProxy' to type 'Automation.Pages.ToolbarElements.ElementsWithActiveState.ActiveStateElements'.

Here is my test:

[TestFixture]
[Category("unit")]
class ActiveStateElementBehaviorTests
{
    [Test]
    public void GetCurrentElementState_StateIsActive_ReturnActive()
    {
        var moqElement = new Mock<IActiveState>();
        moqElement.Setup(x => x.IsElementInActiveState()).Returns(() => true);

        var behavior = new ActiveStateElementBehavior(moqElement.Object);
        behavior.GetCurrentElementState().Should().BeEquivalentTo(ElementState.Active);
    }
}

Here is my code:

public class ActiveStateElementBehavior : IElementStateBehavior
{
    public ActiveStateElementBehavior(IActiveState toolbarElement)
    {
        Element = (ActiveStateElements)toolbarElement;
    }

    public ENAEPToolbarElement Element { get; }

    public ElementState GetCurrentElementState()
    {
        var element = (ActiveStateElements) Element;
        return element.IsElementInActiveState() ? ElementState.Active :
             element.IsButtonInEnabledState() ? ElementState.Default : 
             ElementState.Disabled;
    }
}

public interface IActiveState
{
    bool IsElementInActiveState();
}
like image 784
Nikolay Advolodkin Avatar asked Feb 13 '18 18:02

Nikolay Advolodkin


1 Answers

Your mock is of IActiveState, not ActiveStateElements.

When you call new Mock<IActiveState>() it is creating some new type on the fly that implements the interface IActiveState. This new type is not convertible to ActiveStateElements, which means the cast is gonna fail in the constructor.

You could create the mock like var moqElement = new Mock<ActiveStateElements>(), but I imagine that won't work. The methods on ActiveStateElements are likely not virtual, so you wouldn't be able to setup any of the methods.

The real issue is that ActiveStateElementBehavior says to consumers "I need something that implements IActiveState". And then internally it requires an instance of ActiveStateElements.

You should define whatever other methods that you need on IActiveState, and ActiveStateElementBehavior shouldn't have any casts or references to ActiveStateElements. It should only be aware of the interface IActiveState

like image 55
FUR10N Avatar answered Nov 13 '22 16:11

FUR10N