java测试类只能是静态的吗_java – 对调用静态方法的类进行单元测试

在单元测试Java类A时遇到问题,因为A依赖于类B的静态方法,而B方法内部又有ServiceAdapter的依赖。在测试中,尝试模拟ServiceAdapter以避免NullPointerException,但遇到困难。解决方案是重构B类的静态方法为非静态,并通过构造函数或setter注入B到A,以便在测试中使用B的模拟实例。这样可以确保真正测试的是A类的公共接口,而不是它的依赖。同时,减少类的依赖数量和公共方法有利于更轻松的单元测试。
摘要由CSDN通过智能技术生成

我试图对一个类’A’进行单元测试,该类调用类’B’的静态方法.类’B’本质上具有google guava缓存,其在给定密钥的情况下从缓存中检索值(Object),或者使用服务适配器将对象加载到缓存中(在缓存未命中的情况下).服务适配器类又具有其他自动连接依赖项来检索对象.

这些是用于说明目的的类:

A级

public class A {

public Object getCachedObject(String key) {

return B.getObjectFromCache(key);

}

}

B级

public class B {

private ServiceAdapter serviceAdapter;

public void setServiceAdapter(ServiceAdapter serAdapt) {

serviceAdapter = serAdapt;

}

private static final LoadingCache CACHE = CacheBuilder.newBuilder()

.maximumSize(100)

.expireAfterWrite(30, TimeUnit.MINUTES)

.build(new MyCacheLoader());

public static Object getObjectFromCache(final String key) throws ExecutionException {

return CACHE.get(warehouseId);

}

private static class MyCacheLoader extends CacheLoader {

@Override

public Object load(final String key) throws Exception {

return serviceAdapter.getFromService(key)

}

}

}

服务适配器类

public class ServiceAdapter {

@Autowired

private MainService mainService

public Object getFromService(String key) {

return mainService.getTheObject(key);

}

}

我能够成功地进行集成测试,并从缓存中获取(或加载)该值.但是,我无法为A类编写单元测试.这是我尝试过的:

A级单元测试

@RunWith(EasyMocker.class)

public class ATest {

private final static String key = "abc";

@TestSubject

private A classUnderTest = new A();

@Test

public void getCachedObject_Success() throws Exception {

B.setServiceAdapter(new ServiceAdapter());

Object expectedResponse = createExpectedResponse(); //some private method

expect(B.getObjectFromCache(key)).andReturn(expectedResponse).once();

Object actualResponse = classUnderTest.getCachedObject(key);

assertEquals(expectedResponse, actualResponse);

}

}

当我运行单元测试时,它在ServiceAdapter类中失败并出现NullPointerException,其中调用:mainService.getTheObject(key).

如何在单元测试类A时模拟ServiceAdapter的依赖性.我不应该只关心类A具有的直接依赖性,即. B.

我确信我做的事情从根本上是错误的.我该如何为A级编写单元测试?

解决方法:

您现在知道为什么静态方法被认为是单元测试的不良做法,

因为他们使嘲弄几乎不可能,尤其是如果他们是有状态的.

因此,将B静态方法重构为一组非静态公共方法更为实际.

A类应该通过构造函数或setter注入获得B类实例.在你的ATest中,你然后使用类B的模拟实例化A类,并根据你的测试用例返回你想要的任何东西,并根据你的断言来确定它.

通过这样做,你真的测试了单元,它最终应该是A类的公共接口.(这也是我喜欢一个类在理想世界中只有一个公共方法的原因.)

关于你的具体例子:B的模拟也不应该关心它自己的依赖.您目前在测试中写道:

B.setServiceAdapter(new ServiceAdapter());

你在ATest.不在BTest. ATest应该只有B的模拟,因此不需要传递ServiceAdapter的实例.

你应该只关心A的公共方法是如何表现的,并且鉴于B公共方法的某些反应,这可能会改变.

我也觉得奇怪的是,你想要测试的方法基本上只是B的包装器.也许这在你的情况下有意义但这也暗示我你可能想要在A中注入一个Object而不是B的实例.

如果你不想在模仿地狱中迷失方向,那么每个类的公共方法就越少,从而尽可能减少依赖关系.我努力争取每班三个依赖,并在特殊场合允许最多五个. (每个依赖项可能会对模拟开销产生巨大影响.)

如果您有太多依赖项,当然可以将某些部分移动到其他/新服务.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值