如何断言已使用 moq 和 mspec 对此模拟依赖项调用了方法?

发布于 2024-12-15 08:26:34 字数 3211 浏览 1 评论 0原文

我正在测试一个模型存储库,看看它是否调用消息总线。我不确定这是否是一个很好的测试,但这是我的想法:我通常会将bus.send放入控制器(这是一个MVC Web应用程序),但因为我不想专门测试我的控制器逻辑上,我将其移至存储库中。就我而言,控制器很简单。存储库使用总线和模型数据库来构建视图模型。

无论如何,这个问题的重点是我正在运行的最小起订量测试。我模拟了总线并想验证它是否是从存储库中调用的。

测试如下所示:

public class when_creating_new_clinic
{
    Establish context = () =>
    {
        clinicID = Guid.NewGuid();
        model = new ClinicModel
        {
            ClinicID = clinicID,
            Alias = "alias",
            Title = "title"
            // stuff omitted
        };
        newClinicData = new NewClinicData
        {
            ClinicID = clinicID,
            Alias = "alias",
            Title = "title"
            // stuff omitted 
        };
        cmd = new CreateClinicCmd(newClinicData);
        bus = new Mock<IMessageBusAgent>();
        repository = new ClinicModelRepository(bus.Object);

        bus.Setup(b => b.Send(cmd));
    };

    Because it = () => repository.Create(model);

    It should_send_create_clinic_command_to_bus = () =>
    {
        bus.Verify(b => b.Send(cmd), Times.Exactly(1));
    };

    static ClinicModelRepository repository;
    static ClinicModel model;
    static Mock<IMessageBusAgent> bus;
    static NewClinicData newClinicData;
    static Guid clinicID;
    static CreateClinicCmd cmd;
}

存储库的要点是:

public class ClinicModelRepository : IClinicModelRepository
{
    private readonly IMessageBusAgent m_bus;

    public ClinicModelRepository(IMessageBusAgent bus)
        : this()
    {
        m_bus = bus;
    }

    public void Create(ClinicModel clinicModel)
    {
        // stuff omitted (data is mapped from clinicModel)          

        m_bus.Send(new CreateClinicCmd(data));
    }
}

IMessageBusAgent 声明为:

public interface IMessageBusAgent : IDomainCommandSender, IDomainEventPublisher, IUnitOfWork
{
}

测试结果如下所示:

when creating new clinic

» 应将创建诊所命令发送到总线(失败)

测试“应将创建诊所命令发送到总线”失败的: Moq.MockException: 预期对模拟调用恰好 1 次,但实际上是 0 次:b => b.Send(when_creating_new_clinic.cmd)

Configured setups:
b => b.Send<CreateClinicCmd>(when_creating_new_clinic.cmd), Times.Never

Performed invocations:
IDomainCommandSender.Send(ArReg.Commands.CreateClinicCmd)
IUnitOfWork.Commit()
at Moq.Mock.ThrowVerifyException(MethodCall expected, IEnumerable`1 setups, IEnumerable`1 actualCalls, Expression expression, Times times, Int32 callCount)
at Moq.Mock.VerifyCalls(Interceptor targetInterceptor, MethodCall expected, Expression expression, Times times)
at Moq.Mock.Verify[T](Mock mock, Expression`1 expression, Times times, String failMessage)
at Moq.Mock`1.Verify(Expression`1 expression, Times times)
Repositories\when_creating_new_clinic.cs(51,0): at ArReg.Tests.Specs.Repositories.when_creating_new_clinic.<.ctor>b__4()
at Machine.Specifications.Model.Specification.InvokeSpecificationField()
at Machine.Specifications.Model.Specification.Verify()

0 个通过,1 个失败,0 个跳过,耗时 3.58 秒(Machine.Specifications 0.4.24-f7fb6b5)。

Send() 命令是在 IDomainCommandSender 中声明的,那么我需要如何设置测试以便验证正确的调用?

谢谢

I was testing a model repository to see if it calls the message bus. I am not sure if this is a good test at all but here is my thinking: I would normally put the bus.send into the controller (this is an MVC web app) but since I don't want to test my controllers specifically for logic, I moved this into the repository. Controllers are simple in my case. Repository uses the bus and the model database to build the view models.

Anyways, point of this problem is the moq test I am running. I mocked the bus and wanted to verify that it is called from the repository.

The test looks like this:

public class when_creating_new_clinic
{
    Establish context = () =>
    {
        clinicID = Guid.NewGuid();
        model = new ClinicModel
        {
            ClinicID = clinicID,
            Alias = "alias",
            Title = "title"
            // stuff omitted
        };
        newClinicData = new NewClinicData
        {
            ClinicID = clinicID,
            Alias = "alias",
            Title = "title"
            // stuff omitted 
        };
        cmd = new CreateClinicCmd(newClinicData);
        bus = new Mock<IMessageBusAgent>();
        repository = new ClinicModelRepository(bus.Object);

        bus.Setup(b => b.Send(cmd));
    };

    Because it = () => repository.Create(model);

    It should_send_create_clinic_command_to_bus = () =>
    {
        bus.Verify(b => b.Send(cmd), Times.Exactly(1));
    };

    static ClinicModelRepository repository;
    static ClinicModel model;
    static Mock<IMessageBusAgent> bus;
    static NewClinicData newClinicData;
    static Guid clinicID;
    static CreateClinicCmd cmd;
}

The gist of the repository is this:

public class ClinicModelRepository : IClinicModelRepository
{
    private readonly IMessageBusAgent m_bus;

    public ClinicModelRepository(IMessageBusAgent bus)
        : this()
    {
        m_bus = bus;
    }

    public void Create(ClinicModel clinicModel)
    {
        // stuff omitted (data is mapped from clinicModel)          

        m_bus.Send(new CreateClinicCmd(data));
    }
}

The IMessageBusAgent is declared as:

public interface IMessageBusAgent : IDomainCommandSender, IDomainEventPublisher, IUnitOfWork
{
}

The result of the test looks like this:

when creating new clinic

» should send create clinic command to bus (FAIL)

Test 'should send create clinic command to bus' failed:
Moq.MockException:
Expected invocation on the mock exactly 1 times, but was 0 times: b => b.Send(when_creating_new_clinic.cmd)

Configured setups:
b => b.Send<CreateClinicCmd>(when_creating_new_clinic.cmd), Times.Never

Performed invocations:
IDomainCommandSender.Send(ArReg.Commands.CreateClinicCmd)
IUnitOfWork.Commit()
at Moq.Mock.ThrowVerifyException(MethodCall expected, IEnumerable`1 setups, IEnumerable`1 actualCalls, Expression expression, Times times, Int32 callCount)
at Moq.Mock.VerifyCalls(Interceptor targetInterceptor, MethodCall expected, Expression expression, Times times)
at Moq.Mock.Verify[T](Mock mock, Expression`1 expression, Times times, String failMessage)
at Moq.Mock`1.Verify(Expression`1 expression, Times times)
Repositories\when_creating_new_clinic.cs(51,0): at ArReg.Tests.Specs.Repositories.when_creating_new_clinic.<.ctor>b__4()
at Machine.Specifications.Model.Specification.InvokeSpecificationField()
at Machine.Specifications.Model.Specification.Verify()

0 passed, 1 failed, 0 skipped, took 3.58 seconds (Machine.Specifications 0.4.24-f7fb6b5).

The Send() command is declared in the IDomainCommandSender so how do I need to setup the test so that I can verify the correct call?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

旧故 2024-12-22 08:26:34

您的总线起订量设置有一个小错误。它应该是这样的:

bus.Setup(b => b.Send(It.IsAny<CreateClinicCmd>()));

原因:您使用 CreateClinicCmd 实例编写了设置,在上面创建了两行代码。在您的测试类 ClinicModelRepository 中,您创建该类的另一个实例并调用您的总线模拟。此调用与您在设置中编写的调用不匹配。

Your setup of the bus-moq has a little mistake. It should be like this:

bus.Setup(b => b.Send(It.IsAny<CreateClinicCmd>()));

Reason: You wrote your setup with an instance of CreateClinicCmd created two code lines above. In your class under test ClinicModelRepository you create another instance of that class and call your bus mock. This call doesn't match the call you wrote in your setup.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文