gpt4 book ai didi

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

转载 作者:IT老高 更新时间:2023-10-28 13:51:49 26 4
gpt4 key购买 nike

我在尝试从 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 的情况下使其工作。任何帮助将不胜感激。

提前致谢。

最佳答案

简答

你必须 unwrap the proxy并在目标对象上设置字段:

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;
}

...长一个

这个问题相当复杂,但可以解决。正如您已经猜到的,这是使用 CGLIB 代理的副作用。原则上,Spring 会为您的 FooServiceImpl 创建一个子类,其名称类似于 FooServiceImpl$EnhancerByCGLIB。此子类包含对原始 FooServiceImplreference 以及... FooServiceImpl 具有的所有字段(这是可以理解的 - 这是一个子类)。

所以实际上有两个变量:FooServiceImpl$EnhancerByCGLIB.fooDaoFooServiceImpl.fooDao。您正在为前者分配一个模拟,但您的服务使用后者... I wrote前段时间关于这个陷阱。

关于spring - 模拟 CGLIB 代理服务的属性不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9033874/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com