无法实例化 class 的代理。找不到无参数构造函数
Can not instantiate proxy of class. Could not find a parameterless constructor
我在 .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);`
错误:
Can not instantiate proxy of class:
Microsoft.WindowsAzure.Storage.Blob.CloudBlobClient. Could not find a
parameterless constructor.
如何解决上述问题
问题是 moq
无法创建 CloudBlobClient
,因为它没有无参数构造函数。但是 moq
能够创建没有无参数构造函数的对象,但您需要提供参数。
最简单的方法是使用 this 构造函数
public CloudBlobClient (
Uri baseUri, System.Net.Http.DelegatingHandler delegatingHandler = null);
并提供 Uri
。
类似于:
var mockCloudBlobClient = new Mock<CloudBlobClient>(new Uri("http://mytest"));
当您模拟实现而不是接口时,经常会出现这种情况。如果一个对象有一个接口,通常模拟那个接口会容易得多。
例如,假设这个工人 class:
//worker.cs
public class TemplateWorker : ITemplateWorker
{
private readonly ITemplateRetriever templateRetriever;
public TemplateWorker(ITemplateRetriever templateRetriever)
{
this.templateRetriever = templateRetriever ??
throw new ArgumentNullException(nameof(templateRetriever));
}
//..class body
}
如果你试图模拟这个,你会在这个 post
中得到错误
tests.cs
var mockWorker = Mock.Of<TemplateWorker>();
//!!Can not instantiate proxy of class TestProject.TemplateWorker :
//!! Could not find a parameterless constructor.'
但是,如果我改为模拟接口...没有错误!这很好,因为大部分时间在模拟中我们只关心这个 class 如何消耗其依赖项的 public 合同中的项目。
var mockWorker = Mock.Of<ITemplateWorker>();
//setup what should happen when I call its method...
Mock.Get(mockWorker).Setup(x=>x.SomeMethod(....//;
我在 .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);`
错误:
Can not instantiate proxy of class: Microsoft.WindowsAzure.Storage.Blob.CloudBlobClient. Could not find a parameterless constructor.
如何解决上述问题
问题是 moq
无法创建 CloudBlobClient
,因为它没有无参数构造函数。但是 moq
能够创建没有无参数构造函数的对象,但您需要提供参数。
最简单的方法是使用 this 构造函数
public CloudBlobClient (
Uri baseUri, System.Net.Http.DelegatingHandler delegatingHandler = null);
并提供 Uri
。
类似于:
var mockCloudBlobClient = new Mock<CloudBlobClient>(new Uri("http://mytest"));
当您模拟实现而不是接口时,经常会出现这种情况。如果一个对象有一个接口,通常模拟那个接口会容易得多。
例如,假设这个工人 class:
//worker.cs
public class TemplateWorker : ITemplateWorker
{
private readonly ITemplateRetriever templateRetriever;
public TemplateWorker(ITemplateRetriever templateRetriever)
{
this.templateRetriever = templateRetriever ??
throw new ArgumentNullException(nameof(templateRetriever));
}
//..class body
}
如果你试图模拟这个,你会在这个 post
中得到错误tests.cs
var mockWorker = Mock.Of<TemplateWorker>();
//!!Can not instantiate proxy of class TestProject.TemplateWorker :
//!! Could not find a parameterless constructor.'
但是,如果我改为模拟接口...没有错误!这很好,因为大部分时间在模拟中我们只关心这个 class 如何消耗其依赖项的 public 合同中的项目。
var mockWorker = Mock.Of<ITemplateWorker>();
//setup what should happen when I call its method...
Mock.Get(mockWorker).Setup(x=>x.SomeMethod(....//;