C# 使用模拟存储库对象测试服务
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16800236/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Testing a service using mock repository objects
提问by
I am testing a service within a framework.
我正在测试框架内的服务。
In order to initialize the service, I am using mock repository objects.
为了初始化服务,我使用了模拟存储库对象。
ServiceTest.cs
服务测试文件
private IRepository _repository;
private IService _service;
private List<Object> _objects;
[TestInitialize]
public void Initialize()
{
_repository = new Mock<IRepository>().Object;
_service = new Service(repository);
_objects = new List<Object>()
{
new Object { Name = "random", ID = 1 },
new Object { Name = "not so random", ID = 1},
new Object { Name = "random", ID = 2 },
new Object { Name = "not so random", ID = 2}
};
//attempt at mocking the repository
_repository.Setup(r => r.GetObjects(It.IsAny<string>(), It.IsAny<int>())).Returns(_objects.Where(o => o.Name == _objects.Name && o.ID == _objects.ID).ToList());
}
[TestMethod]
public void GetObjects_ReturnObjectsList()
{
//Arrange
var name = "random";
//Act
var objects = _service.RetrieveObjects(name, 2);
//Assert
Assert.AreEqual(name, objects.Single().Name);
}
However, when I test the service, I get ArgumentNullExceptions. The variables set to the repository method calls return null, and eventually throws an error when business logic is run.
但是,当我测试服务时,我得到ArgumentNullExceptions. 设置到存储库方法的变量调用 return null,并最终在业务逻辑运行时抛出错误。
Service.cs
服务.cs
public List<Objects> RetrieveObjects(string name, int id)
{
var getObjects = repository.GetObjects(name, id); //getObjects return null
DoLogic(getObjects); //ArgumentNullException is thrown here
return getObjects;
}
I have looked up information on mocking repositories, but seems like I will have a lot to setup just to test. I am wondering if the setup is worth it.
我已经查找了有关模拟存储库的信息,但似乎我将有很多设置只是为了测试。我想知道设置是否值得。
Why am I getting ArgumentNullExceptions? Is there a way to test methods that call repositories?
为什么我得到ArgumentNullExceptions?有没有办法测试调用存储库的方法?
采纳答案by ianaldo21
You just need to Setup what is being tested so in your arrange do something like:
您只需要设置正在测试的内容,以便在您的安排中执行以下操作:
var repository = new Mock<IRepository>();
repository.Setup(x => x.GetObjects(It.IsAny<string>()).Returns("whatever getobjects should be returned, maybe a mock object or string");
var service = new Service(repository.Object());
//Continue your test
回答by Sunny Milenov
var entity1 = new MyEntity();
var entity2 = new MyEntity();
var entities = new List<MyEntity>{entity1, entity2};
var mockRepository = new Mock<IRespository>();
mockRepository.Setup(r => r.GetObjects("some param")).Returns(entities);
var service = new Service(mockRepository.Object);
service.DoWork("some param");
//continue the test
回答by Janez Lukan
You should test your SUT (subject under test) in isolation. Don't try to mock existing classes, use interfaces only. That way you won't depend on other objects, who could potentially be buggy. Often you won't be able to setup callbacks and returns of existing classes used as mocks. Mocking interfaces allows you to control and predict the return values.
您应该单独测试您的 SUT(被测对象)。不要试图模拟现有的类,只使用接口。这样你就不会依赖其他可能有问题的对象。通常,您将无法设置用作模拟的现有类的回调和返回。模拟接口允许您控制和预测返回值。
So in your particular case, you should do as @ianaldo21 proposed, I'd just change first line to:
因此,在您的特定情况下,您应该按照@ianaldo21 的建议进行操作,我只需将第一行更改为:
var repository = new Mock<IRepository>();
and then do the setup, and pass the repository.Object to Service.
然后进行设置,并将 repository.Object 传递给 Service。
Instead of asserting the state of SUT, you should test the behavior and interactions of SUT with other objects. So you could have something like this:
您应该测试 SUT 与其他对象的行为和交互,而不是断言 SUT 的状态。所以你可以有这样的事情:
repository.Verify(x => x.GetObjects("test"));
That way, you often need much less setting up for the tests.
这样,您通常需要更少的测试设置。

