C# Moq:使用模拟参数设置通用方法
我一直试图用NUnit为我的泛型方法编写一些测试,但没有成功。我希望我能把我的情况说清楚,因为我不得不大量地解释我的代码 DoBusinessLogic()是我要测试的方法。它从基类调用另外两个方法:C# Moq:使用模拟参数设置通用方法,c#,unit-testing,nunit,moq,C#,Unit Testing,Nunit,Moq,我一直试图用NUnit为我的泛型方法编写一些测试,但没有成功。我希望我能把我的情况说清楚,因为我不得不大量地解释我的代码 DoBusinessLogic()是我要测试的方法。它从基类调用另外两个方法: public class MySvc : BaseSvc, IMySvc { private readonly IMyRepo _repo; private readonly IMyConnectorClass _connector public MySvc(IMyRepo
public class MySvc : BaseSvc, IMySvc
{
private readonly IMyRepo _repo;
private readonly IMyConnectorClass _connector
public MySvc(IMyRepo repo) : base(repo)
{
_repo = repo;
_connector = _repo.GetConnector();
}
public async Task DoBusinessLogic(int id1, int id2){
bool doesFirstObjectExist = await CheckMainObjExists<Foo>(id1, _connector);
await CheckSubObjExists<Bar>(id2, _connector);
// further business logic
}
}
公共类MySvc:BaseSvc,IMySvc
{
私人只读IMyRepo(u repo),;
专用只读IMyConnectorClass\u连接器
公共MySvc(IMyRepo回购):基础(回购)
{
_回购=回购;
_连接器=_repo.GetConnector();
}
公共异步任务DoBusinessLogic(int id1,int id2){
bool doesFirstObjectExist=wait CheckMainObjExists(id1,_连接器);
等待检查是否存在(id2,_连接器);
//进一步的业务逻辑
}
}
这些方法依次调用相同的存储库方法,但其后面有不同的逻辑:
public abstract class BaseSvc : IBaseSvc
{
private readonly IBaseRepo _repo
protected BaseSvc(IBaseRepo repo)
{
_repo = repo;
}
protected async Task<bool> CheckMainObjExists<T>(int? id, IMyConnectorClass connector)
{
return await _repo.GetObjectByIdAsync<T>(Id, connector) != null;
}
protected async Task CheckSubObjExists<T>(int? id, IMyConnectorClass connector)
{
if (await _repo.GetObjectByIdAsync<T>(Id, connector) == null)
{ throw new Exception("Object not found!"); }
}
}
公共抽象类BaseSvc:IBaseSvc
{
私有只读IBaseRepo\u repo
受保护的BaseSvc(IBaseRepo回购)
{
_回购=回购;
}
受保护的异步任务CheckMainObjExists(int?id,IMyConnectorClass连接器)
{
return wait _repo.GetObjectByIdAsync(Id,连接器)!=null;
}
受保护的异步任务检查子对象存在(int?id,IMyConnectorClass连接器)
{
if(wait _repo.GetObjectByIdAsync(Id,连接器)==null)
{抛出新异常(“找不到对象!”;}
}
}
接下来,我想在MySvc类中为DoBusinessLogic()编写一个单元测试。不幸的是,我似乎无法模拟来自存储库的响应
[TestFixture]
public class MySvcTests
{
private MySvc _svc;
private Mock<IMyRepo> _repoMock;
private Mock<IMyConnectorClass> _connectorMock;
[SetUp]
public void SetUp()
{
_repoMock = new Mock<IMyRepo>() {};
_connectorMock = new Mock<IMyConnectorClass>();
_repo.SetUp(r => r.GetConnector()).Return(_connectorMock.Object);
_svc = new MySvc(_repoMock);
}
/*
My intent in this test, is to make CheckMainObjExists() pass,
but make CheckSubObjExist() fail.
*/
[Test]
public async Task DoBusinessLogic_If2ndObjectNotExist_ThrowException()
{
// This should return an object
_repoMock.Setup(r => r.GetObjectByIdAsync<Foo>(It.IsAny<int>(), _connectorMock.Object))
.ReturnsAsync(new Foo());
// This should return null
_repoMock.Setup(r => r.GetObjectByIdAsync<Bar>(It.IsAny<int>(), _connectorMock.Object))
.ReturnsAsync((Bar) null);
Assert.Throws<Exception>(await _svc.DoBusinessLogic());
}
}
[TestFixture]
公共类测试
{
私人MySvc_svc;
私人模拟(repoMock),;
专用模拟(u connectorMock),;
[设置]
公共作废设置()
{
_repoMock=newmock(){};
_connectorMock=newmock();
_repo.SetUp(r=>r.GetConnector()).Return(_connectorMock.Object);
_svc=新的MySvc(_repoMock);
}
/*
我在这个测试中的目的是让CheckMainObjExists()通过,
但要使checkSubbjectExist()失败。
*/
[测试]
公共异步任务DoBusinessLogic_If2ndObjectNotExist_ThroweException()
{
//这应该返回一个对象
_repoMock.Setup(r=>r.GetObjectByIdAsync(It.IsAny(),_connectorMock.Object))
.ReturnsAsync(新Foo());
//这应该返回null
_repoMock.Setup(r=>r.GetObjectByIdAsync(It.IsAny(),_connectorMock.Object))
.ReturnsAsync((Bar)null);
Assert.Throws(wait _svc.DoBusinessLogic());
}
}
然而,当我运行测试时,我为模拟回购设置的两个方法都返回null,而我期望第一个方法返回“true”。
我不知道问题出在哪里,但我怀疑:
我刚刚测试了这段代码,它按预期运行。现在我不得不做很多假设,只是为了让代码编译和运行,这意味着我对您的代码的测试有缺陷,因为我可能已经修复了您的示例中遗漏的某些内容 我没有对您的测试设置代码进行任何更改,这很有效
[TestClass]
public class MySvcTests {
[TestMethod]
[ExpectedException(typeof(Exception))]
public async Task DoBusinessLogic_If2ndObjectNotExist_ThrowException() {
var _repoMock = new Mock<IMyRepo>() { };
var _connectorMock = new Mock<IMyConnectorClass>();
_repoMock.Setup(r => r.GetConnector()).Returns(_connectorMock.Object);
var _svc = new MySvc(_repoMock.Object);
// This should return an object
_repoMock.Setup(r => r.GetObjectByIdAsync<Foo>(It.IsAny<int>(), _connectorMock.Object))
.ReturnsAsync(new Foo());
// This should return null
_repoMock.Setup(r => r.GetObjectByIdAsync<Bar>(It.IsAny<int>(), _connectorMock.Object))
.ReturnsAsync((Bar)null);
await _svc.DoBusinessLogic(0, 0);
}
}
[TestClass]
公共类测试{
[测试方法]
[ExpectedException(typeof(Exception))]
公共异步任务DoBusinessLogic_If2ndObjectNotExist_ThroweException(){
var_repoMock=new Mock(){};
var_connectorMock=new Mock();
_repoMock.Setup(r=>r.GetConnector())。返回(_connectorMock.Object);
var _svc=newmysvc(_repoMock.Object);
//这应该返回一个对象
_repoMock.Setup(r=>r.GetObjectByIdAsync(It.IsAny(),_connectorMock.Object))
.ReturnsAsync(新Foo());
//这应该返回null
_repoMock.Setup(r=>r.GetObjectByIdAsync(It.IsAny(),_connectorMock.Object))
.ReturnsAsync((Bar)null);
wait_svc.DoBusinessLogic(0,0);
}
}
如何将模拟传递给被测试的类?没有看到任何注入点。@Nkosi通过IoC。我更新了帖子以便澄清。无论是CheckMainObjExists
还是checksubbjexists
都不使用传递的id
参数。示例中的输入错误或真实问题?@AdsNobrega您需要提供一个帮助我们了解问题所在的示例。您删除了太多的细节,测试与正在测试的代码不匹配。@Nkosi,我深表歉意。我已经完成了我帖子中的代码,我希望它现在更清晰。我问题的主要焦点是下面的_repoMock方法的设置。