英文:
Stub private methods in class under test in junit 5, PowerMock not working with JUnit5
问题
以下是您要翻译的内容:
我想要为测试中的目标类存根一个私有方法。我正在使用 junit 5
。我以前使用过 powermock
来实现这一点。不幸的是,junit 5
与 powermock
不兼容。
我已经简化了示例以更好地解释这个问题。我有一个类,其中包含一个在公共方法内部调用的私有辅助方法,如下所示:
public class Service {
private Repository repository;
public Object findById(String id) {
Object object = repository.findById(id);
object = verify(object);
return object;
}
private Object verify(Object object) {
//为简洁起见已删除
return object;
}
}
现在我想对 Service
的方法 findById
进行单元测试。我已经使用了 junit 5 和 mockito 来为 Service 类实现单元测试。
public class ServiceUTest {
@InjectMocks
private Service service;
@Mock
private Repository repository;
@BeforeEach
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testFindById() {
when(repository.findById(Mockito.any())).thenReturn(new Object());
//如何对 verify 方法进行存根
}
}
我将非常感谢任何帮助和解决这个问题的指导。
谢谢,
英文:
I want to stub a private method in the class under test. I am using junit 5
. I have used before powermock
to achieve this. Unfortunately junit 5
does not work with powermock
.
I have simplified the example to better explain the problem. I have class that has has private helper method that is called inside public methods. Like below:
public class Service {
private Repository repository;
public Object findById(String id) {
Object object = repository.findById(id);
object = verify(object);
return object;
}
private Object verify(Object object) {
//removed for simplicity
return object;
}
}
Now I want to unit test the method findById
of Service
. I have used junit 5 with mockito to implement unit test for the Service class.
public class ServiceUTest {
@InjectMocks
private Service service;
@Mock
private Repository repository;
@BeforeEach
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testFindById() {
when(repository.findById(Mockito.any())).thenReturn(new Object());
//how to stub verify method
}
}
I would appreciate any help and guide to solve this problem.
Regards,
答案1
得分: 0
public class ServiceUTest {
@InjectMocks
private Service service;
@Mock
private Repository repository;
@BeforeEach
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testFindById() {
// Arrange
Service spyService = spy(service);
when(repository.findById(Mockito.any())).thenReturn(new Object());
PowerMockito.when(spyService, "verify", any()).thenReturn(expectedObjectReturn);
// Act
Object actual = spyService.findById("id");
// Assert
}
}
英文:
You can spy service and use PowerMockito
to define the behavior for verify()
method.
public class ServiceUTest {
@InjectMocks
private Service service;
@Mock
private Repository repository;
@BeforeEach
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testFindById() {
// Arrange
Service spyService = spy(service);
when(repository.findById(Mockito.any())).thenReturn(new Object());
PowerMockito.when(spyService, "verify", any()).thenReturn(expectedObjectReturn);
// Act
Object actual = spyService.findById("id");
// Assert
}
}
答案2
得分: 0
通常,单元测试应该验证一个单元的公共接口。
桩方法私有 - 这是一个不好的主意。在这种情况下,您的测试与实现细节紧密耦合。通常,您希望测试行为而不是实现。
我的建议是从 repository
返回一个对象,该对象将以您希望存根化的方式符合验证逻辑。
解决这种问题的另一种方法是将有趣的部分移到一个新的类中。然后,您可以将其作为依赖项注入到您的服务中。
例如,您可以使用规格模式来提取验证逻辑。
英文:
Generally, a unit test is supposed to verify the public interface of a unit.
Stubbing private methods - is a bad idea. In this case, your tests are tightly coupled to the implementation details. And usually, you want to test the behavior but not implementation.
My suggestion is to return from repository
such object which will comply with verification logic in a way you wanted to stub it.
Another approach to address such issues is to move out interesting bits into a new class. So then you can inject it as a dependency into your service.
For example, you can use Specification pattern to extract verification logic.
专注分享java语言的经验与见解,让所有开发者获益!
评论