当前位置: 首页 > 面试题库 >

模拟CGLIB代理服务的属性不起作用

彭梓
2023-03-14
问题内容

尝试从Junit测试中模拟服务的属性时遇到问题:

@ContextConfiguration("classpath:application-config.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class FooServiceTests {

    @Autowired
    private FooServiceImpl fooService;

    @Test
    public void testFoo() {
        String str = fooService.foo();
        assertEquals("Var", str);
    }

    @Before
    public void mockFooDao() throws Exception {
        FooDao mockFooDao = Mockito.mock(FooDao.class);
        Mockito.when(mockFooDao.foo()).thenReturn("Var");
        ReflectionTestUtils.setField(fooService, "fooDao", mockFooDao);
    }
}

模拟fooDao无效,因为结果不是预期的。这是服务和DAO的代码:

@Service("fooService")
public class FooServiceImpl implements FooService {

    @Autowired
    protected FooDao fooDao;

    @Override
    public String foo() {
        return fooDao.foo();
    }
}

@Repository
public class FooDaoImpl implements FooDao {

    @Override
    public String foo() {
        return "foo";
    }
}

如我们所见,实际的服务旨在返回“ foo”,但是测试模拟了dao,因此服务返回了“ var”。我知道这是与CGLIB代理相关的事情,但是我不知道如何在不对fooDao属性使用setter的情况下使其工作。任何帮助,将不胜感激。

谨在此致谢。


问题答案:

Short answer

你必须解开代理并在目标对象上设置字段:

ReflectionTestUtils.setField(unwrapFooService(), "fooDao", mockFooDao);

在unwrapFooService()可被定义为如下:

private FooServiceImpl unwrapFooService() {
  if(AopUtils.isAopProxy(fooService) && fooService instanceof Advised) {
      Object target = ((Advised) fooService).getTargetSource().getTarget();
      return (FooServiceImpl)target;
  }
  return null;
}

…long one

这个问题很复杂,但是可以解决。你已经猜到这是使用CGLIB代理的副作用。原则上,Spring创建你的FooServiceImpl名为的子类,类似于FooServiceImpl$EnhancerByCGLIB。该子类包含对原始以及所有字段的引用(这是可以理解的-这是一个子类)。FooServiceImplFooServiceImpl

因此实际上有两个变量:FooServiceImpl$EnhancerByCGLIB.fooDaoFooServiceImpl.fooDao。你分配一个模拟前者,但你的服务使用后者。我写了前段时间关于这个陷阱。



 类似资料:
  • 我有一个ASP. NET核心Web API。 一个endpoint,它接受一个名为搜索的模型。它有一个名为表达式类型查询的属性。这个表达式对象有子类。 我将以下JSON发布到我的endpoint(应用程序的内容类型/JSON) {"查询":{"字段ID":"主体","值":"蛋糕","运算符":"匹配"}} 首先,查询参数只是基本表达式——一个多态性问题! 所以我以为是定制的模型活页夹。 我可以针

  • 我在删除服务帐户中的用户时出错,我应该删除另一个用户。之后,Dataprep停止运行作业。 我已经检查了关于dataflow和DataPrep的所有准则:如果API是启用的(是的,它是启用的)。如果有一个适当的服务帐户(是)。但我不知道给这些账户分配什么规则。 我尝试为该帐户分配“云数据流服务代理”角色,但它不适合我 附:我的英语正在进步,有些错误很抱歉。

  • 问题内容: 我在Python中使用时遇到了一些困难: 测试实际上返回正确的值,但它是Mock对象,不是。您如何在Python库中模拟属性? 问题答案: 您需要使用和: 这意味着:调用时,在该调用的返回值上,为属性设置a以返回value 。

  • 我想为以下e2e场景添加一个测试: 我的应用程序通过内部代理服务器向外部服务发出web请求,代理服务器操作请求主体,将请求转发给目的主机,并返回返回的响应。 例如,我向(通过)发送请求。 代理服务器修改请求以填充 cc 详细信息,并将其转发到带有正文 外部。服务返回状态OK。代理服务器返回响应而不进行修改。 如何使用线束测试此工作流?我可以为做但我不知道如何使线对代理与我的网络客户端的代理设置一起

  • 我在一个android应用程序中工作,正在使用一个DialogFragment来显示一个对话框,我想让那个DialogFragment不可取消。我已经将对话框可取消属性设置为false,但它仍然不受影响。 请查看我的代码,并建议我一个解决方案。

  • 我的一个Mapstruct映射器没有使用另一个映射器与 我们的将实体映射到DTO。一个包含一个属性,我正在尝试从该属性映射到一个DTO。 因此,问题在于嵌套对象,即到。 以下是源代码: 从ValidationSupport NeedMapper.java: 来自ActivityMapper.java: 来自ValidationSupportNeedEntity.java(实体) 来自Validat