Nunit 测试相关提交 - 按 ID

发布于 2025-01-11 05:58:50 字数 1278 浏览 0 评论 0原文

我有一个执行两次提交的方法 - 这是它的简化版本:

    public void methodA(objectA objA, List<objectB> objB) 
    {
         _repoA.AddAsync(objA);
         var id = _repoA.SaveChanges();
         if(id > 0) {
            foreach (var ob in objB)
            {
              ob.objAId = id;
              _repoB.AddRange(ob);
            }
           _repoB.SaveChanges();
         }
   }

How do I get/set the id in my unit test to see if my list's objAId is set 并且它实际上包含两个对象 - 现在因为我无法在第一次提交中设置/获取 id ,所以我的测试失败了:

[Fact]
    public async void test()
    {
        var objA = new ObjA(null);
        var objB = new List<ObjB>
        {
           new ObjB(null, null, "Test"),
           new ObjB(null, null, "Test2")
        });

        var result = await _sut.methodA(objA, objB);

        Assert.NotNull(result);
        _mockFieldRepository.Verify(x => x.InsertAsync(It.IsAny<MyObjectA>()), Times.Once);
        _mockFieldOptionRepository.Verify(x => x.InsertAsync(It.IsAny<MyObjectB>()), Times.Once); //fails here
        _mockFieldOptionRepository.Verify(x => x.InsertAsync(It.Is<MyObjectB>(p => p.Id > 0 && p.objAId == objA.Id))); //fails here

    }

I have a method that does two commits - here is a simplified version of it:

    public void methodA(objectA objA, List<objectB> objB) 
    {
         _repoA.AddAsync(objA);
         var id = _repoA.SaveChanges();
         if(id > 0) {
            foreach (var ob in objB)
            {
              ob.objAId = id;
              _repoB.AddRange(ob);
            }
           _repoB.SaveChanges();
         }
   }

How do I get/set the id in my unit test to see if my list's objAId is set and that it actually contains two object - right now as I cannot set/get id in first commit my test fails:

[Fact]
    public async void test()
    {
        var objA = new ObjA(null);
        var objB = new List<ObjB>
        {
           new ObjB(null, null, "Test"),
           new ObjB(null, null, "Test2")
        });

        var result = await _sut.methodA(objA, objB);

        Assert.NotNull(result);
        _mockFieldRepository.Verify(x => x.InsertAsync(It.IsAny<MyObjectA>()), Times.Once);
        _mockFieldOptionRepository.Verify(x => x.InsertAsync(It.IsAny<MyObjectB>()), Times.Once); //fails here
        _mockFieldOptionRepository.Verify(x => x.InsertAsync(It.Is<MyObjectB>(p => p.Id > 0 && p.objAId == objA.Id))); //fails here

    }

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

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

发布评论

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

评论(1

只是在用心讲痛 2025-01-18 05:58:50

注意:我必须猜测您的一些测试设置和接口被模拟,因此我的答案可能不完全正确。

如果我们采用您的原始代码,则似乎没有安装模拟来配置什么代码预计会发生。您只是使用“验证”来确保某些事情确实发生了。

因此,我们需要做的第一件事是配置模拟,使隐含的模拟出现错误,并设置期望。

_mockFieldRepository = new Mock<IFieldRepository>(MockBehaviour.Strict);

您现在会发现出现测试错误,因为 SaveChanges 和 AddRange 不是安装程序。这很好。因此也为它们添加设置。

_mockFieldRepository.Setup(x => x.SaveChanges();
_mockFieldRepository.Setup(x => x.AddRange(It.IsAny<MyObjectA>());
_mockFieldRepository.Setup(x => x.InsertAsync(It.IsAny<MyObjectA>()));
_mockFieldOptionRepository.Setup(x => x.InsertAsync(It.IsAny<MyObjectB>()));
_mockFieldOptionRepository.Setup(x => x.InsertAsync(It.Is<MyObjectB>(p => p.Id > 0 && p.objAId == objA.Id)));

使用 It.Is<> 是个好主意。在设置过程中,或者对于简单参数(整数、字符串等),只需传递预期值,而不是 It.Is。

在我看来,验证不是很好,因为 It.IsAny<>() 意味着,您不关心该函数是如何被调用的,所以您应该使用 It.Is (如第三个设置)来使 100%确保您期望传递给方法的参数是您确实获得的参数。

NOTE: I have to guess at some of your test setup and interfaces being mocked, so my answer may not be completely correct.

If we take your original code, there appears to be no Setup mocks to configure what the code is expecting to happen. You are simply using Verify to make sure that some things DID happen.

So, the first thing we need to do is configure mock so that implied mocks are errors, and also Setup the expectations.

_mockFieldRepository = new Mock<IFieldRepository>(MockBehaviour.Strict);

You will now find that you get test errors because SaveChanges and AddRange are not Setup. This is good. So add Setups for them too.

_mockFieldRepository.Setup(x => x.SaveChanges();
_mockFieldRepository.Setup(x => x.AddRange(It.IsAny<MyObjectA>());
_mockFieldRepository.Setup(x => x.InsertAsync(It.IsAny<MyObjectA>()));
_mockFieldOptionRepository.Setup(x => x.InsertAsync(It.IsAny<MyObjectB>()));
_mockFieldOptionRepository.Setup(x => x.InsertAsync(It.Is<MyObjectB>(p => p.Id > 0 && p.objAId == objA.Id)));

It's a good idea to use It.Is<> during setup, or for simple parameters (integers, strings etc), just pass the expected value, rather than It.Is.

In my opinion, the validation is not great, because It.IsAny<>() means, you don't care how that function is being called, so you should use It.Is (like the 3rd setup) to make 100% certain that the parameters you expect to be passed to the method ARE the parameters you do get.

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