英文:
Mockito: how verify static method called in non-static method?
问题
我有一个`Animal.class`:
```java
class Animal {
int counter;
public void move() {
counter += getRandomNumber(1, 10);
}
public static int getRandomNumber(int min, int max) {
return new Random().nextInt(min, max);
}
}
我使用Mockito 5.2.0
。
尝试使用mockedStatic
接口验证getRandomNumber
方法:
@Test
void tryVerifyStaticMethod() {
try (MockedStatic<Animal> mockedStatic = mockStatic(Animal.class)) {
mockedStatic.verify(() -> Animal.getRandomNumber(1, 10), times(1));
}
}
但我不知道如何在测试中调用非静态的move()
方法以调用getRandomNumber
方法。
<details>
<summary>英文:</summary>
I have `Animal.class`:
class Animal {
int counter;
public void move() {
counter += getRandomNumber(1, 10);
}
public static int getRandomNumber(int min, int max) {
return new Random().nextInt(min, max);
}
}
I use `Mockito 5.2.0`.
Tried verify `getRandomNumber` method with `mockedStatic` interface:
@Test
void tryVerifyStaticMethod() {
try (MockedStatic<Animal> mockedStatic = mockStatic(Animal.class)) {
mockedStatic.verify(() -> Animal.getRandomNumber(1, 10), times(1));
}
}
But I don't know how call non-static `move()` method in the test for invoking `getRandomNumber` method.
</details>
# 答案1
**得分**: 2
以下是您要翻译的内容:
如果您想调用一个正在调用您的静态模拟的方法,您可以在try块中简单地执行它。只要您的静态模拟存在,它将用于这些调用。
这意味着,您的测试可以如下所示:
```java
@Test
void tryVerifyStaticMethod() {
try (MockedStatic<Animal> mockedStatic = mockStatic(Animal.class)) {
// 如果需要,为您的静态模拟设置一些行为
mockedStatic.when(() -> Animal.getRandomNumber(1, 10)).thenReturn(42);
// 创建一个新的Animal实例
Animal animal = new Animal();
// 调用要测试的方法
animal.move();
// 断言计数器已更改
assertEquals(42, animal.counter);
// 验证随机数方法的调用
mockedStatic.verify(() -> Animal.getRandomNumber(1, 10), times(1));
}
}
只要您在try
块内部调用move()
,所有对您的Animal
类的静态调用都将使用mockedStatic
对象及其所有行为。在这个示例中,我设置了每当调用具有min
= 1和max
= 10的getRandomNumber
方法时返回42
的行为。
英文:
If you want to call a method that is calling your static mocks, you can do it simply in the try-block. As long as your static mock is present, it will be used for the calls.
This means, your test could look like the following:
@Test
void tryVerifyStaticMethod() {
try (MockedStatic<Animal> mockedStatic = mockStatic(Animal.class)) {
// Giving your static mock some behaviour if you want
mockedStatic.when(() -> Animal.getRandomNumber(1, 10)).thenReturn(42);
// creating a new instance of animal
Animal animal = new Animal();
// calling the method under test
animal.move();
// asserting that the counter has changed
assertEquals(42, animal.counter);
// verifying the call of the random number method
mockedStatic.verify(() -> Animal.getRandomNumber(1, 10), times(1));
}
}
As long as you are calling move()
inside the try
, all the static calls to your Animal
class will use the mockedStatic
object and all of its behaviours. In this example case, I gave the behaviour to return 42
whenever getRandomNumber
with min
= 1 and max
= 10 is called.
答案2
得分: 1
以下是您要翻译的内容:
首先,不要测试类的内部细节,而是测试其行为。在您的情况下,我会像这样重写动物类:
class Animal {
int counter;
Random random;
public Animal(Random random) {
this.random = random;
}
public void move() {
counter += getRandomNumber(1, 10);
}
// 必须有一个方法显示调用move()的效果
public int getCounter() {
return counter;
}
private int getRandomNumber(int min, int max) {
return random.nextInt(min, max);
}
}
然后您的测试如下所示:
@Test
public void testMove() {
Random random = mock(Random.class);
when(random.nextInt(1, 10)).thenReturn(5);
Animal animal = new Animal(random);
animal.move();
assertEquals(5, animal.getCounter());
}
避免在您希望进行测试的类中调用 new
。如果您愿意,可以将 getRandomNumber
设置为 static
,并将 Random
实例作为参数传递给它,但我没有看到这样做的好理由。
英文:
First, don't test the internal details of your class, test its behaviour. In your case I would rewrite animal like this:
class Animal {
int counter;
int Random random;
public Animal(Random random) {
this.random = random;
}
public void move() {
counter += getRandomNumber(1, 10);
}
// there must be some method which shows the effect of calling move()
public int getCounter() {
return counter;
}
private int getRandomNumber(int min, int max) {
return random.nextInt(min, max);
}
}
Then your test becomes:
@Test
public void testMove() {
Random random = mock(Random.class);
when(random.nextInt(1, 10)).thenReturn(5);
Animal animal = new Animal(random);
animal.move();
assertEquals(5, animal.getCounter());
}
Avoid calling new
in classes which you wish to test.
You can keep getRandomeNumber
as static
, if you wish, and pass it the Random
instance as a parameter, but I don't see any good reason to do that.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论