使用 Moq,System.InvalidCastException:无法将“Castle.Proxies.ObjectProxy”类型的对象转换为类型

问题描述 投票:0回答:2

有人可以帮我解决这个错误消息吗?我不明白为什么演员阵容不起作用:

消息:System.InvalidCastException:无法转换类型的对象 输入“Castle.Proxies.ObjectProxy” 'Automation.Pages.ToolbarElements.ElementsWithActiveState.ActiveStateElements'。

这是我的测试:

[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);
    }
}

这是我的代码:

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();
}
c# unit-testing mocking moq
2个回答
20
投票

你的模拟是

IActiveState
,而不是
ActiveStateElements

当您调用

new Mock<IActiveState>()
时,它会动态创建一些实现接口
IActiveState
的新类型。 这个新类型不能转换为
ActiveStateElements
,这意味着构造函数中的转换将会失败。

你可以像

var moqElement = new Mock<ActiveStateElements>()
一样创建模拟,但我想这行不通。
ActiveStateElements
上的方法可能不是
virtual
,因此您无法设置任何方法。

真正的问题是

ActiveStateElementBehavior
对消费者说“我需要一些实现
IActiveState
的东西”。然后在内部它需要一个
ActiveStateElements
的实例。

您应该在

IActiveState
上定义所需的任何其他方法,并且
ActiveStateElementBehavior
不应该有任何对
ActiveStateElements
的强制转换或引用。它应该只知道接口
IActiveState


0
投票

现有的答案很好,我将给出另一个答案,因为您经常会在 HealthChecks 中遇到它:

尝试测试一下:

public class StartupBackgroundService : BackgroundService
{
 protected override Task ExecuteAsync(CancellationToken stoppingToken)
 {
    using (var scope = _services.CreateScope())
    {
        // TAKE NOTE OF THE SERVICE YOU NEED TO MOCK
        var healthCheck = scope.ServiceProvider.GetRequiredService<HealthCheckService>();   
        var report = healthCheck.CheckHealthAsync();

我必须像这样模拟 Scope 和 HealthCheckService:

// Arrange
var mockHealthCheck = new Mock<HealthCheckService>(); // <--  THIS HAS TO BE CORRECT OTHERWISE YOU GET THE ERROR IN QUESTION
var mockStartCheck = new Mock<StartupHealthCheck>();
var mockLogger = new Mock<ILogger<StartupHealthCheck>>();

var serviceProvider = new Mock<IServiceProvider>();
serviceProvider.Setup(provider => provider.GetService(typeof(HealthCheckService))).Returns(mockHealthCheck.Object);

var serviceScope = new Mock<IServiceScope>();
serviceScope.Setup(x => x.ServiceProvider).Returns(serviceProvider.Object);

var serviceScopeFactory = new Mock<IServiceScopeFactory>();
serviceScopeFactory
    .Setup(x => x.CreateScope())
    .Returns(serviceScope.Object);

serviceProvider
    .Setup(x => x.GetService(typeof(IServiceScopeFactory)))
    .Returns(serviceScopeFactory.Object);

var service = new StartupBackgroundService(mockStartCheck.Object, serviceProvider.Object, mockLogger.Object);

// Act

// This magically calls ExecuteAsync
var res = service.StartAsync(It.IsAny<CancellationToken>()); 
© www.soinside.com 2019 - 2024. All rights reserved.