Lig*_*ng3 1 c# unit-testing mstest moq
我对 Moq 感到困惑,我不确定这里有什么问题。
我想测试依赖于 ILeadStorageService 的 LeadService,并且我想以这种方式配置 Moq - 返回与安装程序中传递的 GUID 匹配的对象。
问题出在 Moq Setup/Returns 行中,因为当我将依赖对象替换为其真实实例时 - 测试通过,但完全错误。我不想只测试 LeadService,而不是从属存储。
public LeadService( IConfigurationDbContext configurationDbContext,
ILeadStorageService leadStorageService,
ILeadDeliveryService deliveryService)
{
this.configurationDbContext = configurationDbContext;
this.leadStorageService = leadStorageService;
this.deliveryService = deliveryService;
}
Run Code Online (Sandbox Code Playgroud)
测试方法
public TestLeadResponse ProcessTestLead(TestLeadRequest request)
{
var response = new TestLeadResponse()
{
Status = TestLeadStatus.Ok
};
try
{
var lead = leadStorageService.Get(request.LeadId);
if (lead == null)
{
throw new LeadNotFoundException(request.LeadId);
}
var buyerContract =
configurationDbContext.BuyerContracts.SingleOrDefault(bc => bc.Id == request.BuyerContractId);
if (buyerContract == null)
{
throw new BuyerContractNotFoundException(request.BuyerContractId);
}
response.DeliveryEntry = deliveryService.DeliverLead(lead, buyerContract);
}
catch (LeadNotFoundException e)
{
response.Status = TestLeadStatus.LeadNotFound;
response.StatusDescription = e.Message;
}
catch (BuyerContractNotFoundException e)
{
response.Status = TestLeadStatus.BuyerContractNotFound;
response.StatusDescription = e.Message;
}
return response;
}
Run Code Online (Sandbox Code Playgroud)
然后在测试准备中:
[TestInitialize]
public void Initialize()
{
_leadIdStr = "2c3ac0c0-f0c2-4eb0-a55e-600ae3ada221";
_dbcontext = new ConfigurationDbContext();
_lead = PrepareLeadObject();
_buyerContract = PrepareBuyerContractObject(Id : 1, BuyerContractId : 1, BuyerTag: "GAME");
_leadDeliveryMock = new Mock<ILeadDeliveryService>();
_leadStorageMock = new Mock<ILeadStorageService>();
_leadStorageService = new LeadStorageService("LeadGeneration_Dev");
}
private Lead PrepareLeadObject()
{
var lead = new Lead() {CountryId = 1, Country = "NL", Id = Guid.Parse(_leadIdStr)};
return lead;
}
Run Code Online (Sandbox Code Playgroud)
和测试本身:
[TestMethod]
public void LeadServiceTest_ProcessTestLeadWithWrongBuyerContractIDThrowsBuyerContractNotFoundException()
{
_leadDeliveryMock
.Setup(methodCall => methodCall.DeliverLead(_lead, _buyerContract))
.Returns<LeadDeliveryEntry>((r) => PrepareLeadDeliveryEntry());
// here is the problem!!!!
_leadStorageMock.Setup(mc => mc.Get(_leadId)).Returns((Lead l) => PrepareLeadObject());
//if i change to real object - test passes
//_service = new LeadService(_dbcontext, _leadStorageService, _leadDeliveryMock.Object);
_service = new LeadService(_dbcontext, _leadStorageMock.Object, _leadDeliveryMock.Object);
var response = _service.ProcessTestLead(new TestLeadRequest() { BuyerContractId = int.MaxValue, LeadId = _leadId });
Assert.IsNotNull(response);
Assert.AreEqual(response.Status, TestLeadStatus.BuyerContractNotFound);
}
Run Code Online (Sandbox Code Playgroud)
我在 _leadStorageMock.Setup().Returns() 中缺少什么?
Returns扩展方法接受一个与您正在模拟的方法具有相同参数的委托。这些参数将在调用模拟方法期间传递给委托。因此Lead,您将获得传递给mc.Get方法的参数而不是对象- 潜在客户 ID:
_leadStorageMock.Setup(mc => mc.Get(_leadId))
.Returns((Guid leadId) => PrepareLeadObject());
Run Code Online (Sandbox Code Playgroud)
检查与返回值时访问调用参数相关的快速入门部分。
请注意,有一堆Returns扩展方法接受值函数作为参数:
Returns<T>(Func<T, TResult> valueFunction);
Returns<T1, T2>(Func<T1, T2, TResult> valueFunction);
Returns<T1, T2, T3>(Func<T1, T2, T3, TResult> valueFunction);
// etc
Run Code Online (Sandbox Code Playgroud)
如您所见,这些值函数计算从模拟方法返回的值,但它们都接收不同数量的参数(最多 16 个)。这些参数将与您正在模拟的方法的参数完全匹配,并且它们将在被valueFunction模拟方法的调用期间传递给。因此,如果您使用两个参数模拟某个函数,则应使用相应的扩展名:
mock.Setup(m => m.Activate(It.IsAny<int>(), It.IsAny<bool>())
.Returns((int i, bool b) => b ? i : 0); // Func<T1, T2, TResult>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2043 次 |
| 最近记录: |