【问题标题】:Can not instantiate proxy of class. Could not find a parameterless constructor无法实例化类的代理。找不到无参数构造函数
【发布时间】:2019-11-21 04:49:05
【问题描述】:

我在 .Net Core 中使用 xUnit 和 Moq 编写测试用例时遇到了突出的问题

我使用 MSTest Fakes 编写了下面的测试用例。它按预期工作。

 [TestClass]
public class TestBlobServiceProvider
{
    private Common.Interfaces.IBlobServiceProvider _iblobprovider;

    public TestBlobServiceProvider()
    {
        Common.Interfaces.IBlobServiceProvider iblobprovider = new BlobServiceProvider();
        this._iblobprovider = iblobprovider;
    }

    public TestBlobServiceProvider(string storageConnectionString)
    { 

    }


    [TestMethod]
    public void Move_Success()
    {
        using (ShimsContext.Create())
        {
            string sourceContainer = "a";
            string destinationContainer = "s";
            string sourceFileName = "d";
            string destinationFileName = "e";

            Microsoft.WindowsAzure.Storage.Blob.Fakes.ShimCloudBlockBlob sourceFile = new Microsoft.WindowsAzure.Storage.Blob.Fakes.ShimCloudBlockBlob ();
            Microsoft.WindowsAzure.Storage.Blob.Fakes.ShimCloudBlockBlob destFile = new Microsoft.WindowsAzure.Storage.Blob.Fakes.ShimCloudBlockBlob();

            Microsoft.WindowsAzure.Storage.Blob.Fakes.ShimCloudBlockBlob.AllInstances.StartCopyCloudBlockBlobAccessConditionAccessConditionBlobRequestOptionsOperationContext = (x, y, z, d, e,s) =>
            { 
                     return "Hi"; 
            };

            Microsoft.WindowsAzure.Storage.Blob.Fakes.ShimCloudBlob.AllInstances.DeleteDeleteSnapshotsOptionAccessConditionBlobRequestOptionsOperationContext = (x, y, z, d, e) =>
           {

           };

            Microsoft.WindowsAzure.Storage.Blob.Fakes.ShimCloudBlobClient.AllInstances.GetContainerReferenceString = (x, y) =>
            {
                return new Microsoft.WindowsAzure.Storage.Blob.Fakes.ShimCloudBlobContainer();
            };

            Microsoft.WindowsAzure.Storage.Blob.Fakes.ShimCloudBlobContainer.AllInstances.CreateIfNotExistsAsync = (x) =>
            {
                return Task.Run(() =>
                {
                   return new bool();
                });
            };

            Microsoft.WindowsAzure.Storage.Blob.Fakes.ShimCloudBlobContainer.AllInstances.GetBlockBlobReferenceString = (x, y) =>
            {
                return new Microsoft.WindowsAzure.Storage.Blob.Fakes.ShimCloudBlockBlob();

            };


            CDM.Common.Fakes.ShimBlobServiceProvider.AllInstances.GetBlockBlobContainerString = (x, y) =>
            {
                return new Microsoft.WindowsAzure.Storage.Blob.Fakes.ShimCloudBlobContainer();
            };

            this._iblobprovider.Move( sourceContainer,  destinationContainer,  sourceFileName,  destinationFileName);

        }

    }
}

但现在我们需要迁移到 .Net Core 。因此,我开始使用 xUnit 测试用例,因为 .Net 核心缺少 Fakes 支持。

下面的代码是 xUnit 和 Moq

public class TestBlobServiceProvider
{
    private readonly Common.Interfaces.IBlobServiceProvider _iblobprovider;

    public TestBlobServiceProvider()
    {
        Common.Interfaces.IBlobServiceProvider iblobprovider = new BlobServiceProvider();
        this._iblobprovider = iblobprovider;
    }

    [Fact]
    public void Move_Success()
    {
            string sourceContainer = "a";
            string destinationContainer = "s";
            string sourceFileName = "d";
            string destinationFileName = "e";

            var uri = new Uri("https://app.blob.core.windows.net/container/https://app.blob.core.windows.net/container/Accounts/Images/acc.jpg");

            CloudBlockBlob source = null;
            AccessCondition sourceAccessCondition = null;
            AccessCondition destAccessCondition = null;
            BlobRequestOptions options = null;
            OperationContext operationContext = null;
            CloudBlobContainer container = new CloudBlobContainer (uri);
            Task task = null;
            DeleteSnapshotsOption deleteSnapshotsOption = new DeleteSnapshotsOption();


            var mockCloudBlobClient = new Mock<Microsoft.WindowsAzure.Storage.Blob.CloudBlobClient>();
            mockCloudBlobClient.Setup(repo => repo.GetContainerReference("sample")).Returns(container);

            var mockCloudBlobContainer = new Mock<Microsoft.WindowsAzure.Storage.Blob.CloudBlobContainer>();
            mockCloudBlobContainer.Setup(repo => repo.GetBlockBlobReference("sample")).Returns(new CloudBlockBlob(uri));

            mockCloudBlobContainer.Setup(repo => repo.CreateIfNotExistsAsync()).Returns(Task.Run(() =>
            {
                return new bool();
            }));


           var mockCloudBlob = new Mock<Microsoft.WindowsAzure.Storage.Blob.CloudBlob>();
            mockCloudBlob.Setup(repo => repo.DeleteAsync(deleteSnapshotsOption, sourceAccessCondition, options, operationContext)).Returns(task);

            var mockCloudBlockBlob = new Mock<Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob>();
            mockCloudBlockBlob.Setup(repo => repo.StartCopyAsync(source, sourceAccessCondition, destAccessCondition, options, operationContext)).ReturnsAsync("Hi");

            Common.Interfaces.IBlobServiceProvider obj = new BlobServiceProvider(mockCloudBlobClient.Object, mockCloudBlobContainer.Object, mockCloudBlob.Object, mockCloudBlockBlob.Object);

            obj.Move(sourceContainer, destinationContainer, sourceFileName, destinationFileName);

        //   this._iblobprovider.Move(sourceContainer, destinationContainer, sourceFileName, destinationFileName);

    }
}

我在

处遇到错误
Common.Interfaces.IBlobServiceProvider obj = new BlobServiceProvider(mockCloudBlobClient.Object, mockCloudBlobContainer.Object, mockCloudBlob.Object, mockCloudBlockBlob.Object);`

错误:

无法实例化类的代理: Microsoft.WindowsAzure.Storage.Blob.CloudBlobClient。找不到 无参数构造函数。

如何解决上述问题

【问题讨论】:

  • CloudBlobClient 没有 moq 可以用来创建代理的无参数构造函数。因此出现错误。
  • 我现在能做什么?我不能为 CloudBlobClient 方法编写模拟/单元测试。如果我不为 CloudBlobClient 方法创建 Mock,那么它们将在 BlobServiceProvider 类方法中抛出错误,阻止我继续进行。
  • var mockCloudBlobClient = new Mock&lt;Microsoft.WindowsAzure.Storage.Blob.CloudBlobClient&gt;(new Uri("http://mytest")); 试试这个...
  • @Johnny,谢谢。问题已解决。
  • @chandrasekhar 如果提供的答案解决了问题,请将其标记为答案。

标签: .net .net-core moq xunit microsoft-fakes


【解决方案1】:

问题在于 moq 无法创建 CloudBlobClient,因为它没有无参数构造函数。但是 moq 能够在没有无参数构造函数的情况下创建对象,但您需要提供参数。

最简单的方法是使用this构造函数

public CloudBlobClient (
    Uri baseUri, System.Net.Http.DelegatingHandler delegatingHandler = null);

并提供Uri

类似:

var mockCloudBlobClient = new Mock<CloudBlobClient>(new Uri("http://mytest"));

【讨论】:

    【解决方案2】:

    当您模拟实现而不是接口时,经常会出现这种情况。如果一个对象有一个接口,通常模拟该接口会容易得多。

    例如,想象一下这个工人阶级:

    //worker.cs
    public class TemplateWorker : ITemplateWorker
        {
            private readonly ITemplateRetriever templateRetriever;
            
            public TemplateWorker(ITemplateRetriever templateRetriever)
            {
                this.templateRetriever = templateRetriever ?? 
                   throw new ArgumentNullException(nameof(templateRetriever));
            }
         //..class body
         }
    

    如果你试图模拟这个,你会在这篇文章中得到错误

    tests.cs
    var mockWorker = Mock.Of<TemplateWorker>();
    //!!Can not instantiate proxy of class TestProject.TemplateWorker : 
    //!!  Could not find a parameterless constructor.'
    

    但是,如果我改为模拟界面...没有错误!这很棒,因为在模拟的大部分时间里,我们只关心这个类如何使用其依赖项的公共合约中的项目。

    var mockWorker = Mock.Of<ITemplateWorker>();
    
    //setup what should happen when I call its method...
    Mock.Get(mockWorker).Setup(x=>x.SomeMethod(....//;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-29
      • 2021-06-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多