Mockito: 验证传递给构造函数的参数

huangapple go评论65阅读模式
英文:

Mockito: verify arguments passed to constructor

问题

我正在尝试弄清楚如何验证传递给Mockito模拟构造函数的参数我的代码的简化版本如下

    class Mocked {
        Mocked(String first, String second, int value) {
        }
    }

    class Target {
        void testMe() {
            new Mocked("Hello", "World", 99);
        }
    }


    @Test
    public void test_Target() {
        try (
            MockedConstruction<Mocked> mockedNew = mockConstruction(Mocked.class);
        ) {
            new Target().testMe();

            Mocked mocked = mockedNew.constructed().get(0);
            // TODO: 验证传递给模拟构造函数的所有参数
        }
    }

* 我试图测试的类是"Target"
* Target使用"Mocked"类的实例在实际代码中我将使用实际的Mocked实例但是为了测试的目的我想将其模拟出来以便我可以隔离地测试"Target"我使用了mockConstruction构造函数来做到这一点

在我的代码的最终版本中传递给Mocked构造函数的参数并不是硬编码的相反将会有一些业务逻辑来推导它们所以我想验证它们是否已经正确地推导出来了但是该如何做呢

我在Google上搜索的所有示例都没有显示如何做到这一点而且org.mockito.Mockito.verify()似乎没有一种方法可以测试构造函数

我唯一能想到的解决方案是添加模拟初始化函数将参数复制到局部变量中但是这涉及使这些变量有效地成为final所以是final的单元素数组和丑陋的类型转换肯定有比这更好的办法 

我漏掉了什么
英文:

I'm trying to work out how to verify the parameters passed to a mocked constructor in Mockito. A simplified version of my code is:

class Mocked {
    Mocked(String first, String second, int value) {
    }
}

class Target {
    void testMe() {
        new Mocked(&quot;Hello&quot;, &quot;World&quot;, 99);
    }
}


@Test
public void test_Target() {
    try (
        MockedConstruction&lt;Mocked&gt; mockedNew = mockConstruction(Mocked.class);
    ) {
        new Target().testMe();

        Mocked mocked = mockedNew.constructed().get(0);
        // TODO: verify all arguments passed to mocked
    }
}
  • The class I'm trying to test is "Target"
  • Target uses an instance of the "Mocked" class. In real code code I'll want to use an actual instance of Mocked, but for the purposes of testing I want to mock it out so I can test "Target" in isolation of "Mocked". I've used the mockConstruction construct to do this.

In my final version of my code the arguments passed to the Mocked constructor are not hardcoded. Instead there will be some business logic to derive them, so and I want to verify they have been derived out correctly. But how?

None of the examples I've Googled show show me how to do this, and org.mockito.Mockito.verify() doesn't appear to have a way to test a constructor.

The only solution I can see is to add mock initialiser function that copies the argument into local variables. But this involves making those variables effectively final (so final one element array) and ugly casts. Surely there has to be something better than that!

What have I missed?

答案1

得分: 1

你可以使用 Junit 或你选择的测试库来对传递给 mockedConstructorcontext 参数运行断言,该参数将包含传递给构造函数的参数列表。 (请注意,它们都将被存储为 Object,因此您需要进行强制类型转换) 例如:

try (MockedConstruction&lt;Mocked&gt; mockedConstructor = mockConstruction(Mocked.class, (mock, context) -&gt; {
    assertEquals(&quot;Hello&quot;, (String) context.arguments().get(0));
    assertEquals(&quot;World&quot;, (String) context.arguments().get(1));
    assertEquals(99, (int) context.arguments().get(2));
}))
{
    new Target().testMe();
}
英文:

You can run assertions using Junit or your testing library of choice on the context argument passed into the mockedConstructor, which will have a list of the arguments passed into the constructor. (Note that they will all be stored as Object, so you will need to cast them) e.g.

try (MockedConstruction&lt;Mocked&gt; mockedConstructor = mockConstruction(Mocked.class, (mock, context) -&gt; {
             assertEquals(&quot;Hello&quot;, (String) context.arguments().get(0));
             assertEquals(&quot;World&quot;, (String) context.arguments().get(1));
             assertEquals(99, (int) context.arguments().get(2));
    }))
{
    new Target().testMe();
}

答案2

得分: 0

根据我所知,使用Mockito API 是不可能实现这一点的。

你可以尝试进行设计更改,在这个新的 MockedFactory 类中负责创建 Mocked 对象。你可以为你的测试创建一个 MockMockedFactory 并将其注入到目标对象中以使用。你将能够验证被测试类调用的这个工厂的方法。虽然不是最好的方法,会增加样板代码,但是是可行的。

另外,我猜想新创建的对象如果不返回,那么测试就不会有问题。如果你正在测试的方法不是一次性做太多事情的话,值得考虑一下。也许进行一些重构可以使它更容易进行测试。

或许这个链接会有帮助:https://groups.google.com/g/mockito/c/WqPlcNrvbOw?pli=1

英文:

As far as I know, this is not possible using the Mockito API.

You can try a design change where a new MockedFactory class is responsible for creating Mocked objects. You can create a MockMockedFactory for your tests and inject it into Target to use. You will be able to verify the methods called on this factory by the class under test. Not the nicest, adds boilerplate code, but works.

Also, I guess the newly created object is not returned as testing would not be a problem then. It is worth considering if the method you are testing isn't too big doing too many things at once. Maybe some other refactors could help make it more testable.

Or maybe this one: https://groups.google.com/g/mockito/c/WqPlcNrvbOw?pli=1

huangapple
  • 本文由 发表于 2023年2月19日 23:51:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/75501366.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定