我问了几个JUnit和面向的Mockito最近的问题,我还是很努力获得了它的窍门。 该教程都是为了很简单的例子,所以我努力扩大我的测试案例,为我的课工作。
目前,我想要写一些测试用例的方法我在我的web应用程序的代理商之一。 该方法与一对夫妇的代理内的其它方法进行交互以验证某些对象。 我只是想现在就测试此的一种方法。
这里就是我试图做:
创建我的经纪人像这样的对象的Mockito:
MyProcessingAgent mockMyAgent = Mockito.mock(MyProcessingAgent.class);
设置存根使用Mockito.when像这样(希望正确的术语):
Mockito.when(mockMyAgent.otherMethod(Mockito.any(arg1)).thenReturn(requiredReturnArg);
尝试执行我的方法,像这样:
List myReturnValue = mockMyAgent.methodThatNeedsTestCase();
我期待的事情myReturnValue
,但收到0代替我试图调试。 当我调用该方法,它永远不会执行。 我在那个从未被触及方法的第一线调试点。
如果我想在一个类中的一个方法来执行代码,但强制类中的其他方法(一个人试图与外界的数据库进行交互)返回伪造出来的值。 这是可能的的Mockito?
看来,我目前的做法方法不正确的测试风格,但我不知道如何前进。 我可以嘲笑我的课,并已一个方法,像正常的,而其他方法存根给我回给定值,使我没有测试这种方法之一在处理数据访问被执行?
你混淆了一个Mock
与Spy
。
在一个模拟的所有方法存根,并返回“智能返回类型”。 这意味着,除非你指定行为调用任何方法对嘲笑类不做任何事情 。
在一个间谍类的原始功能仍然存在,但你可以在间谍验证方法调用,并且还覆盖方法的行为。
你需要的是
MyProcessingAgent mockMyAgent = Mockito.spy(MyProcessingAgent.class);
一个简单的例子:
static class TestClass {
public String getThing() {
return "Thing";
}
public String getOtherThing() {
return getThing();
}
}
public static void main(String[] args) {
final TestClass testClass = Mockito.spy(new TestClass());
Mockito.when(testClass.getThing()).thenReturn("Some Other thing");
System.out.println(testClass.getOtherThing());
}
输出是:
Some Other thing
注意:您应该尝试嘲笑被测试的类的依赖性不是类本身。
所以,在测试嘲讽之类的想法是anathima测试的做法。 你不应该这样做。 因为你这样做,你的测试是测试进入的Mockito的嘲讽类不是你的类。
间谍也不会工作,因为这只是提供了围绕窥探类的包装/代理。 一旦执行是类里面也不会去通过代理,因此不打间谍。 更新:虽然我相信这是春天代理的真实似乎没有间谍的Mockito的选择。 我设置了一个场景,方法m1()
调用m2()
我窥探对象和存根m2()
到doNothing
。 当我调用m1()
在我的测试, m2()
之类的没有达到。 调用的Mockito存根。 因此,使用间谍来完成问什么是可能的。 不过,我要重申,我会认为这是不好的做法(恕我直言)
你应该嘲笑所有在其下测试类依赖的类。 这将允许您控制在所测试的方法调用您可以控制这些方法调用类方法的行为。
如果你的类创建其他类的实例,可以考虑使用工厂。
你记起来了吧。 问题是, 在测试类 (CUT)没有内置的单元测试-它没有真正 TDD “d。
想想看这样的...
- 我需要测试类的功能-让我们把它myFunction的
- 这功能使得对函数的调用另一个类/服务/数据库
- 这个功能还呼吁CUT另一种方法
在单元测试
- 要创建一个具体的切断或
@Spy
就可以了 - 您可以
@Mock
所有其他类/服务/数据库(即外部依赖) - 你可以叫存根在CUT其他功能,但它是不是真的如何单元测试应该做的事
为了避免执行代码,你是不是严格的测试,你可以抽象的代码掳到东西,可以是@Mock
版。
在这个非常简单的例子中,创建一个对象的函数将是困难的,以测试
public void doSomethingCool(String foo) {
MyObject obj = new MyObject(foo);
// can't do much with obj in a unit test unless it is returned
}
但是,使用服务来获得MyObject的一个功能是便于测试,我们已经提取了困难/不可能的测试代码到的东西,使得这种方法测试。
public void doSomethingCool(String foo) {
MyObject obj = MyObjectService.getMeAnObject(foo);
}
如MyObjectService可以嘲笑并且还证实.getMeAnObject()被调用与FOO变量。
简答题
如何在你的情况做:
int argument = 5; // example with int but could be another type
Mockito.when(mockMyAgent.otherMethod(Mockito.anyInt()).thenReturn(requiredReturnArg(argument));
长的答案
其实你想要做什么是可能的,至少在Java中8也许你没有得到这个答案由其他人,因为我使用Java 8,允许对与这个问题的Java 8发布之前(即允许通过功能,不仅重视到其他功能)。
让我们模拟一个数据库查询的电话。 该查询返回FreeRoms = X和HotelTable的所有行StarNumber = Y.什么测试期间我想到,就是这个查询会还给不同的酒店列表:每个返回酒店拥有相同的值X和Y,而其他值,我会根据我的需要决定他们。 下面的例子很简单,但当然你可以把它更加复杂。
所以,我创建了一个功能,这将使回不同的结果,但所有的人都FreeRoms = X和StarNumber = Y.
static List<Hotel> simulateQueryOnHotels(int availableRoomNumber, int starNumber) {
ArrayList<Hotel> HotelArrayList = new ArrayList<>();
HotelArrayList.add(new Hotel(availableRoomNumber, starNumber, Rome, 1, 1));
HotelArrayList.add(new Hotel(availableRoomNumber, starNumber, Krakow, 7, 15));
HotelArrayList.add(new Hotel(availableRoomNumber, starNumber, Madrid, 1, 1));
HotelArrayList.add(new Hotel(availableRoomNumber, starNumber, Athens, 4, 1));
return HotelArrayList;
}
也许间谍是更好的(请尝试),但我这样做是在嘲笑类。 这里怎么怎么办?(注意anyInt()的值):
//somewhere at the beginning of your file with tests...
@Mock
private DatabaseManager mockedDatabaseManager;
//in the same file, somewhere in a test...
int availableRoomNumber = 3;
int starNumber = 4;
// in this way, the mocked queryOnHotels will return a different result according to the passed parameters
when(mockedDatabaseManager.queryOnHotels(anyInt(), anyInt())).thenReturn(simulateQueryOnHotels(availableRoomNumber, starNumber));