如何在反映的私有方法上模拟自动装配的私有响应

时间:2019-06-03 21:14:49

标签: java spring maven unit-testing mockito

我正在测试“保存在数据库中”公共方法,该方法还将一些已修改的已保存数据发送到服务。该测试确保它保存了收到的内容,但发送的修改后的数据有所不同。当内部私有方法调用设置为自动装配的存储库时,就会出现问题,因为反映为未初始化自动装配的存储库。

所以首先要断言私有方法的答案是我对私有方法的反思。我用受控的响应模拟了内部自动装配服务,但没有发现如何在我的私有反射上设置模拟服务的答案。

我还是测试的新手,所以我可能会犯一些错误,以便解释会尽力纠正它,并进一步扩展该主题。


这是针对公共方法“ X”的,该方法将某些内容保存在数据库中(返回所保存内容的代码),然后执行其他操作,然后转到私有方法“ Y”以验证一些数据并在该私有方法内转到其他私有方法“ Z”,以创建一些新数据,以从另一个服务“ B”中检索数据并将其从之前的数据中获取,然后将其发送到外部服务“ A”。所有这些都是在同一类实现“ classImpl”中完成的。私有方法“ Z”的接收方式与“ X”方法相同,它使用从“ B”获得的数据生成并返回要在“ A”服务中发送的数据。


@Test
@Rollback(false)
@Transactional(readOnly = false)
TEST{

testData testXData= new testData();
testXData.set()...
testXData.set()...
.......Generate data to be saved.

mockResponse controlledOutput = mock(mockResponse.class);

deliverInMockResponse deliverInMockResponse = new deliverInMockResponse();
deliverInMockResponse.set()...
deliverInMockResponse.set()...
.......Generate data to be delivered in the mockResponse.

when(controlledOutput.findByAnd(otherSomething)).thenReturn(deliverInMockResponse);

assertNotNull(testSaveMethodX(testXData));
String Something = "evalutaThis";
assertEquals(testXData.getSomething(),Something);

try{
      classImpl publicImpl = new classImpl();
      Method method =  classImpl.class.getDeclaredMethod("Z", testData.class);
      method.setAccessible(true);
      methodZResponse Zoutput = (methodZResponse) method.invoke(publicImpl, testXData);
      assertNotEquals(Zoutput.getSomething(),Something);
    }
    catch (Exception e){
      assertNotNull(null);
    }

}

2 个答案:

答案 0 :(得分:0)

对于私有方法的模拟或测试,我建议您尝试PowerMock而不是自己写反射。 here是一个很好的指南。另外Mock private method using PowerMockito

答案 1 :(得分:0)

如果您在测试中运行自己制作的反射代码,那么可能更好地完成了测试代码。

并非所有代码都可以自动进行单元测试。为了能够测试代码,您应该以某种方式编写代码。

您已经在一个问题的代码段中显示了该测试,但是您在此测试的代码也非常重要。 从问题的第一段开始,我假设您有以下内容:

Future[Map[A, Seq[B]]]

由于在测试过程中不会发生自动装配(因为在单元测试中您没有让Spring发挥作用的能力),所以您很难测试class MyDao { @Autowired private SomeService service; public void saveInDb() { // do something with db service.sendData(); } } 方法

但是,此代码有问题,可以重构以进行更好的单元测试:

因此,这里有个提示:不要在字段上使用自动装配,而是使用构造函数注入重写代码:

saveInDb

如果您觉得这是很多代码,甚至可以使用Lombok项目为您生成一个构造函数,但这超出了问题的范围...

一种或另一种方式是,您现在拥有一个类,该类具有定义明确的依赖项列表,必须在尝试创建此类实例的测试中指定必须

在这里单元测试变得容易

class MyDao {
    private SomeService service;
    @Autowired // you can even omit this annotation in recent versions of spring
               // spring will understand what should be injected if there is only one 
               // constructor in the class
    public MyDao(SomeService service) {
        this.service = service;
    }
} 

与袁庆飞给出的先前答案不同,我不建议使用PowerMock / PowerMockito之类的工具,仅在无法更改测试代码的情况下才考虑使用这些工具(通常对于未经测试而编写的旧项目而言,这是正确的)介意)