在单元测试中使用 Moq 时出现问题

发布于 2024-10-06 04:45:04 字数 1173 浏览 2 评论 0原文

我一直在探索模拟对象在单元测试中的使用,并一直在尝试 .NET 的 Moq 框架。我在尝试测试从数据库返回域对象的服务层方法时遇到一些问题。

这是我的设置:

    [SetUp]
    public void DoSetupTasks()
    {
        mockDao = new Mock<IHibernateDao>();
        _hibernateService = new HibernateService(mockDao.Object);
        mockDomainObject = new Mock<DomainBase>();
        dmBase = new DomainBase()
        {
            Id = 5
        };
    }

这是我遇到问题的单元测试。 FindById() 方法根据给定的 ID 和类型返回 DomainBase 对象。

    [Test]
    public void TestFindById()
    {
        mockDomainObject.Setup(dmb => dmb.Id.Equals(It.IsAny<long>())).Returns(true);
        mockDao.Setup(dao => dao.FindById(
            It.IsAny<long>(),
            It.IsAny<Type>()
        )).Returns(mockDomainObject.Object);

        _hibernateService.FindById(dmb.Id, typeof(DomainBase));
        mockDomainObject.VerifySet(dmb => dmb.Id = dmBase.Id);
    }

当我运行单元测试时,它抛出以下异常:

Exception: Invalid setup on a non-virtual (overridable in VB) member: dmb => dmb.Id.Equals(It.IsAny())

我承认,我对这个框架非常不熟悉。我一直在尝试遵循一些教程,但我一直无法弄清楚。

I've been exploring the use of mock objects in unit testing and have been trying out the Moq framework for .NET. I'm having some issues in attempting to test a service-layer method that returns a domain object from a database.

Here is my setup:

    [SetUp]
    public void DoSetupTasks()
    {
        mockDao = new Mock<IHibernateDao>();
        _hibernateService = new HibernateService(mockDao.Object);
        mockDomainObject = new Mock<DomainBase>();
        dmBase = new DomainBase()
        {
            Id = 5
        };
    }

Here is the unit test I am having problems with. The method FindById() returns a DomainBase object based on a given ID and Type.

    [Test]
    public void TestFindById()
    {
        mockDomainObject.Setup(dmb => dmb.Id.Equals(It.IsAny<long>())).Returns(true);
        mockDao.Setup(dao => dao.FindById(
            It.IsAny<long>(),
            It.IsAny<Type>()
        )).Returns(mockDomainObject.Object);

        _hibernateService.FindById(dmb.Id, typeof(DomainBase));
        mockDomainObject.VerifySet(dmb => dmb.Id = dmBase.Id);
    }

When I run the unit test, it throws the following exception:

Exception: Invalid setup on a non-virtual (overridable in VB) member: dmb => dmb.Id.Equals(It.IsAny<Int64>())

I'll admit, I'm pretty unfamiliar with the framework. I've been trying to follow some tutorials on it, but I haven't been able to get it figured out.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

清君侧 2024-10-13 04:45:04

尝试更像这样的事情:

[Test]
public void TestFindById() {

    const int TEST_ID = 5;
    // Configure your mock DAO to return a real DomainBase 
    // when FindById is called.
    mockDao
        .Setup(dao => dao.FindById(TEST_ID, It.IsAny<Type>())
        .Returns(new DomainBase() { Id = TEST_ID });

    var domainObject = _hibernateService.FindById(TEST_ID , typeof(DomainBase));

    // Make sure the returned object is a DomainBase with id == TEST_ID 

    Assert.IsEqual(TEST_ID , domainObject.Id);
    Assert.IsInstanceOf<DomainBase>(domainObject);

    // and verify that your mock DAO was called with the same argument passed to 
    // your NHibernate service wrapper:
    mockDao.VerifyAll();
}

您不需要模拟您的域对象 - 通常最好模拟您的数据层和服务,然后在被测试的逻辑代码和您的逻辑代码之间传递真实的域对象(包含示例/测试数据)模拟服务层。

编辑:要测试保存和删除方法,您需要执行类似的操作。请注意,当调用模拟方法时,我们如何使用 Moq 库的 Callback() 方法来运行一些代码,并且在这个回调中,我们断言传递给我们方法的对象是我们期望的对象:

[Test]
public void TestSaveDomainBase() {

    const int OBJECT_ID = 5;

    mockDao
      .Setup(dao => dao.Save(It.IsAny<DomainBase>()))
      .Callback((DomainBase d) => {
         // Make sure the object passed to Delete() was the correct one
         Assert.AreEqual(OBJECT_ID, d.ID);
      });

    var objectToSave = new DomainObject() { Id = OBJECT_ID };

    _hibernateService.Save(objectToDelete);

    mockDao.VerifyAll();
}


[Test]
public void TestDeleteDomainBase() {

    const int OBJECT_ID_TO_DELETE = 5;

    mockDao
      .Setup(dao => dao.Delete(It.IsAny<DomainBase>()))
      .Callback((DomainBase d) => {
         // Make sure the object passed to Delete() was the correct one
         Assert.AreEqual(OBJECT_ID_TO_DELETE, d.ID);
      });

    var objectToDelete = new DomainObject() { Id = OBJECT_ID_TO_DELETE };

    _hibernateService.Delete(objectToDelete);


    mockDao.VerifyAll();
}

Try something more like this:

[Test]
public void TestFindById() {

    const int TEST_ID = 5;
    // Configure your mock DAO to return a real DomainBase 
    // when FindById is called.
    mockDao
        .Setup(dao => dao.FindById(TEST_ID, It.IsAny<Type>())
        .Returns(new DomainBase() { Id = TEST_ID });

    var domainObject = _hibernateService.FindById(TEST_ID , typeof(DomainBase));

    // Make sure the returned object is a DomainBase with id == TEST_ID 

    Assert.IsEqual(TEST_ID , domainObject.Id);
    Assert.IsInstanceOf<DomainBase>(domainObject);

    // and verify that your mock DAO was called with the same argument passed to 
    // your NHibernate service wrapper:
    mockDao.VerifyAll();
}

You shouldn't need to mock your domain objects - you're generally better off mocking your data layer and services and then passing real domain objects (containing sample/test data) between your logic code under test and your mocked service layers.

EDIT: To test save and delete methods, you'll want to do something like this. Note how we're using the Callback() method of the Moq library to run some code when the mock method is called, and within this callback we're asserting that the object passed to our method was the object we were expecting:

[Test]
public void TestSaveDomainBase() {

    const int OBJECT_ID = 5;

    mockDao
      .Setup(dao => dao.Save(It.IsAny<DomainBase>()))
      .Callback((DomainBase d) => {
         // Make sure the object passed to Delete() was the correct one
         Assert.AreEqual(OBJECT_ID, d.ID);
      });

    var objectToSave = new DomainObject() { Id = OBJECT_ID };

    _hibernateService.Save(objectToDelete);

    mockDao.VerifyAll();
}


[Test]
public void TestDeleteDomainBase() {

    const int OBJECT_ID_TO_DELETE = 5;

    mockDao
      .Setup(dao => dao.Delete(It.IsAny<DomainBase>()))
      .Callback((DomainBase d) => {
         // Make sure the object passed to Delete() was the correct one
         Assert.AreEqual(OBJECT_ID_TO_DELETE, d.ID);
      });

    var objectToDelete = new DomainObject() { Id = OBJECT_ID_TO_DELETE };

    _hibernateService.Delete(objectToDelete);


    mockDao.VerifyAll();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文