【问题标题】:Mocked method do not pass correct value模拟方法不传递正确的值
【发布时间】:2019-12-03 22:07:26
【问题描述】:

我试图了解在 Xunit 中如何使用 AutoFixture 进行模拟。我创建了 Service 和 Repository 类及其接口。模拟方法应该传递不同于默认值的值。

Mocked 方法总是传递默认值而不是我在“.Returns()”中写入的值。我试过 AutoConfiguredMoqCustomization 但它提供了完全随机的值,我无法取回。

Repository.cs

public class Repository : IRepository
{
    public int GetInt()
    {
         return 999;
    }
}

Service.cs

public class Service : IService
{        
    private readonly Repository _repository;

    public Service()
    {
        _repository = new Repository();
    }

    public string GetStringFromInt()
    {
        return _repository.GetInt().ToString();
    }
}

测试

    [Fact]
    public void Test()
    {
        var fixture = new Fixture().Customize(new AutoMoqCustomization());
        var repositoryMock = fixture.Create<Mock<IRepository>>();
        var service = fixture.Create<Service>();

        repositoryMock.Setup(x => x.GetInt()).Returns(1);
        var act = service.GetStringFromInt();

        Assert.Equal("1", act);
    }

正如您在 Repository 中看到的默认值是 999,我期望 repositoryMock 中的值为 1,但结果是“999”而不是“1”。

我明白我的问题了。当我使用自动起订量测试服务声明参数时,必须在所有模拟存储库之后

测试

[Theory, AutoMoqData]
public void Test([Frozen] Mock<IRepository> repositoryMock, Service service)
{
    ...
}

属性

public class AutoMoqDataAttribute : AutoDataAttribute
{
    public AutoMoqDataAttribute() : base(GetDefaultFixture)
    {
    }

    private static IFixture GetDefaultFixture()
    {
        return new Fixture().Customize(new AutoMoqCustomization());
    }
}

【问题讨论】:

    标签: c# xunit autofixture automoq


    【解决方案1】:

    你应该先冻结你的模拟。当您在 AutoFixture 上调用 Create 时,它​​每次都会为您创建一个新实例。在修改后的代码中尝试以下操作(您在构造函数中使用该类型的接口)。

    public class ServiceTests
    {
      private readonly IFixture fixture = new Fixture().Customize(new AutoMoqCustomization());
    
      public ServiceTests() 
      {
        fixture.Register<IService>(() => fixture.Create<Service>());
      }
    
      [Fact]
      public void Test()
      {
        // Arrange
        var repositoryMock = fixture.Freeze<Mock<IRepository>>();
        repositoryMock.Setup(x => x.GetInt()).Returns(1);
    
        var service = fixture.Create<IService>();
    
        // Act
        var act = service.GetStringFromInt();
    
        // Verify
        Assert.Equal("1", act);
      }
    }
    

    要检查您是否正确设置了 autofixture,您可以在以后的单元测试中尝试以下操作。

    
    var repo1 = fixture.Create<IRepository>();
    var repo2 = fixture.Create<IRepository>();
    
    Assert.Equal(repo1.GetHashCode(), repo2.GetHashCode());
    

    如果上述失败,则表明您没有冻结类型。这些代码行让我在过去节省了很多时间......

    【讨论】:

      【解决方案2】:

      您做错了 DI,您没有将 Repository 注入您的服务中。 试试这样。

          public class Repository : IRepository
          {
              public int GetInt()
              {
                  return 999;
              }
          }
      
          public class Service : IService
          {
              IRepository Repository;
              public Service(IRepository repository)
              {
                  this.Repository = repository;
              }
              public string GetStringFromInt()
              {
                  return Repository.GetInt().ToString();
              }
          }
      

      现在,当您模拟 IRepository 时,您可以将其添加到 Service。

      你在构造函数中使用了一个新的 Repository(),所以你正在使用那个实现

      【讨论】:

      • 请提供带有我的接口实现的新代码
      猜你喜欢
      • 1970-01-01
      • 2019-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多