我必须测试某些SLSB的方法,该方法在当前对象上调用另一种方法(使用 this this 关键字),我需要以某种方式对其进行固定。
考虑以下简化代码:
@Local
public interface SomeService{
public int someMethod();
public int anotherMethod();
}
@Stateless()
public class SomeServiceImpl{
@EJB
private SomeDAO sDAO;
public SomeServiceImpl(){}
public SomeServiceImpl(SomeDAO sDAO){
this.sDAO = sDAO;
}
@Override
public int someMethod(){
int dbValue = sDAO.getSomeDBValue(); // 1st stub required here
return dbValue + this.anotherMethod(); // 2nd stub required here
}
@Override
public int anotherMethod(){
return 5;
}
}
到stub getsomedbvalue()方法我可以用@mock和@injectMocks注释将模拟注入此类,但我不知道如何正确地stub eyterMethod()。要存根它,我需要在模拟对象上进行操作,因此我尝试将当前对象作为参数传递,而在测试中只需通过模拟对象即可。例如,如果我的方法看起来像这样(无需使用dao方法)。
@Override
public int someMethod(SomeServiceImpl sS){
return sS.anotherMethod();
}
我用手动创建的模拟测试看起来像这样:
@Test
public void someMethodTest() throws Exception {
SomeServiceImpl sS = mock(SomeServiceImpl.class);
when(sS.someMethod(any(SomeServiceImpl.class))).thenCallRealMethod();
when(sS.anotherMethod()).thenReturn(5);
assertEquals(5, sS.someMethod(sS));
}
方法是在模拟对象上调用的,对对象本身的引用将传递为参数,而另一个method则是固定的。它起作用了,但似乎很丑陋,如果需要使用这样的注释来对我的dao进行模拟怎么办:
@RunWith(MockitoJUnitRunner.class)
public class SomeClassTest{
@Mock
SomeDAO sDAO;
//@Mock //I can't use those 2 annotations at once
@InjectMocks
SomeServiceImpl sS;
@Test
public void someMethodTest() throws Exception {
//...
}
}
我了解@InjectMocks注释用于指示@mock注释的模拟的类,但是对于我的丑陋解决方案,我也需要SomeServiceImpl才能模拟。
我的解决方案甚至接近纠正吗?我应该如何固定另一个方法()正确测试somemethod()?通过模拟的类实例,我在方法参数中测试了哪种方法是一个好主意?如果是,我应该如何处理用注释创建模拟?
在测试相同类的另一种方法时,您不应模拟方法。从理论上讲,您可以做到这一点(使用Mokito间谍例如)。
从这个意义上讲,您正在以错误的层次接近此问题:实际上,您不应该在测试中测试的方法中使用哪些其他方法。您会看到,您想 test someMethod()
确实履行其合同。如果需要在您的生产环境中打电话给anotherMethod()
...您的单位测试有多有价值,那么当它模拟anotherMethod()
时?!
另一个想法:您将问题分开,然后将anotherMethod()
零件移至其自己的X类中。然后可以模拟该实例。