英文:
How to mock a global object in a class properly?
问题
让我们假设我有一个如下所示的类:
Class A{
private K Obj = (K)(AppContext.getSpringContext().getBean("obj"))
public void method1{
// 使用 Obj
}
public void method2{
// 使用 Obj
}
}
我需要为method1和method2编写Junit测试,并在method1和method2中更改Obj的行为。在我的Junit类中,我设置了appcontext如下:
public class AccountInformationManagerTest {
private CCBSAppContext appContext;
@Mock
ApplicationContext springContext;
@Mock
Object obj;
@Before
public void setup() throws Exception {
appContext = new CCBSAppContext();
appContext.setApplicationContext(springContext);
Mockito.when(springContext.getBean("obj")).thenReturn(obj);
}
}
正如你所看到的,我全局设置了appcontext。我不想模拟静态调用,因为我正在使用jacoco,而powermockito与jacoco不太兼容。问题在于appcontext现在是一个全局对象,它在所有方法之间共享,并且我需要在测试这两个方法时修改obj的行为。这将创建并发问题。我该如何解决这个问题?
英文:
Let say I have a class like so
Class A{
private K Obj = (K)(AppContext.getSpringContext().getBean("obj"))
public void method1{
// uses Obj
}
public void method2{
// uses Obj
}
}
And I need to write junits for method1 and method2 by changing the behavior of Obj in method 1 and method 2. In my junit class I am setting the appcontext as so:
public class AccountInformationManagerTest {
private CCBSAppContext appContext;
@Mock
ApplicationContext springContext;
@Mock
Object obj;
@Before
public void setup() throws Exception {
appContext = new CCBSAppContext();
appContext.setApplicationContext(springContext);
Mockito.when(springContext.getBean("obj")).thenReturn(obj);
}
}
As you can see, I am setting globally the appcontext. I don't want mock the static calls as I am using jacoco and powermockito doesn't integrate very well with jacoco. The problem here is that appcontext is now a global object which is shared across all methods and I need to modify the behavior of obj as I test the two methods. This will create a concurrency issue. How can I resolve this?
答案1
得分: 1
避免直接使用 (K)(AppContext.getSpringContext().getBean("obj"))
来注入依赖项,而应通过自动装配或自动注入的方式添加依赖项。然后可以通过 SpringTestUtils 或设置器(setters)轻松进行测试并向类中添加 obj。
@Autowired
K obj;
否则,您可以为每个测试模拟 springContext 的 getBean 方法。
@Test
void fun {
Mockito.when(springContext.getBean(Mockito.eq("obj"))).thenReturn(obj);
// 进行某些操作
}
@Test
void fun2 {
Mockito.when(springContext.getBean(Mockito.eq("obj"))).thenReturn(obj2);
// 进行某些操作2
}
英文:
TBH avoid (K)(AppContext.getSpringContext().getBean("obj"))
directly inject dependency or autowire the dependency . Then in its easily testable and add obj to the class via SpringTestUtils or setters.
@Autowired
K obj;
Else you can mock springContext getBean method for every test
@Test
void fun {
Mockito.when(springContext.getBean(Mockito.eq("obj"))).thenReturn(obj);
// doSomething
}
@Test
void fun2 {
Mockito.when(springContext.getBean(Mockito.eq("obj"))).thenReturn(obj2);
// doSomething2
}
答案2
得分: 1
使用反射来设置Obj
。然后,您可以将Obj
设置为一个模拟对象。
这里有一个描述如何做到这一点的Stack Overflow答案。
英文:
Use reflection to set the Obj
. Then you can set Obj
to be a mocked object.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论