gpt4 book ai didi

java - 打破本地依赖以单元测试无效方法

转载 作者:塔克拉玛干 更新时间:2023-11-01 21:57:33 25 4
gpt4 key购买 nike

我正在练习 mockito,但我对如何测试依赖于对本地对象中方法的调用的方法有点困惑。请参阅以下示例:

public class Worker {          

public void work() {
Vodka vodka = new Vodka();
vodka.drink();
}
}

这个 worker ,他不干活,反而喜欢喝酒。但是我想添加一个测试来证明他在工作时喝酒。但是没有办法这样做,因为我必须在调用方法 work 时验证方法 drink() 被调用。我想你同意我的看法,这是不可能测试的,所以我需要在开始测试之前打破依赖关系。这是我的第一个疑问,您认为打破这种依赖的最好方法是什么?如果我只是将 vodka 对象的范围更改为全局,我认为不会很好(我不想将它暴露给类(class)的其他部分)。我想过创建一个工厂,像这样:

public class Worker {          

private VodkaFactory vodkaFactory = new VodkaFactory();


public void work() {
Vodka vodka = vodkaFactory.getVodka();
vodka.drink();
}
}

我不确定我是否正确地打破了依赖关系,但我现在想做的是测试在执行 work() 时调用了 drink() 方法。我没有运气就试过了:

@Test
public void
does_the_worker_drink_while_working
() {
VodkaFactory vodkaFactory = mock(VodkaFactory.class);
Vodka vodka = mock(Vodka.class);
Worker worker = new Worker();
worker.work();
when(vodkaFactory.getVodka()).thenReturn(vodka);
verify(vodka,times(1)).drink();
}

我模拟了工厂,什么时候会检测到工厂创建了一个新的 Vodka 对象。但是当我想验证该方法是否调用 1 次方法 drink() 时,mockito 告诉我:

Wanted but not invoked:
vodka.drink();
-> at testing_void_methods_from_local_objects.WorkerSpecification.does_the_worker_drink_while_working(WorkerSpecification.java:22)
Actually, there were zero interactions with this mock.

我没有正确 stub 或者我做错了什么。你能帮我完成这个测试,并说明测试这种不可测试方法的最佳方法是什么吗?

我知道 mockito 有一个名为 doAnswer() 的方法,它用于模拟方法调用,您认为它在这种情况下有用吗?我应该如何使用它?

更新:

我正在按照建议在 work() 之前调用 when() 并且我正在尝试允许从外部设置工厂类:

@Test
public void
does_the_worker_drink_while_working
() {
VodkaFactory vodkaFactory = mock(VodkaFactory.class);
Vodka vodka = mock(Vodka.class);
Worker worker = new Worker();
when(vodkaFactory.getVodka()).thenReturn(vodka);
worker.work();
verify(vodka,times(1)).drink();
}

现在是生产代码:

public class Worker {          


private VodkaFactory vodkaFactory;

public void work() {
Vodka vodka = vodkaFactory.getVodka();
vodka.drink();
}

public void setVodkaFactory(VodkaFactory vodkaFactory) {
this.vodkaFactory = vodkaFactory;
}

我得到的异常如下:

 java.lang.NullPointerException
at testing_void_methods_called_from_local_objects.Worker.work(Worker.java:9)

这是说 vodka.drink()

的行

抱歉,我仍然对问题所在感到困惑。

最佳答案

你的 worker 在这里创建他自己的工厂类:

private VodkaFactory vodkaFactory = new VodkaFactory();

您正在创建的模拟完全脱离了工作实例,因此缺乏交互。为了让它工作,工厂必须从“外部”注入(inject) worker ,比如通过 constructor injection .

如果这是遗留代码,您可以使用反射将私有(private)工厂实例替换为模拟实例。

正如 JB Nizet 在评论中指出的那样,您的模拟设置是在调用 work 之后进行的。为了把事情做好,在调用任何使用它的代码之前注入(inject)模拟并设置它。

关于java - 打破本地依赖以单元测试无效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15350239/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com