编辑:以更短的方式重写了问题。感谢您指出了这一点!:)
我需要编写 JUnit 测试,我必须在没有 setter/getter 的情况下模拟几个私有方法和字段。我尝试了两种方法来完成它,使用 Mockito 和 PowerMock。问题是,这两者可以结合吗?首先尝试使用私有字段测试方法:
...
@Mock private XMLConfiguration config;
@InjectMocks AAIGroupController groupi;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
...
given(config.configurationsAt(anyString())).willReturn(ldapGroups);
...
第二次尝试使用 PowerMock 测试私有方法:
...
AAIGroupController groupC = PowerMockito.spy(new AAIGroupController());
...
when(groupC, method(AAIGroupController.class, "getLdapGroupNodeFromGroupConfigFile", ELUser.class))
.withArguments(any(ELUser.class))
.thenReturn(sn);
assertTrue(iaigroupi.isPosixAccount(new ELUserAAI(null, true, false)));
...
有没有办法将它们结合起来,或者我应该只使用 PowerMock?我在用 PowerMock 模拟私有字段时遇到了麻烦。
另一个问题是:我必须为接口编写 JUnit 测试。这是废话吗,因为实现接口的类已经过测试。如果没有,什么是好的做法?
提前致谢!
老问题,完全可以跳过。我只是把它放在这里是为了理解已经给出的答案。
我必须为已经完成实现的接口编写 JUnit 测试。但是我有点困惑如何正确地为他们编写测试。我已经开始实施,但我现在卡住了。首先,我不确定我是否正确测试了接口,然后模拟私有字段存在问题。到目前为止,我已经编写了两个不同的测试类来尝试一些事情。两个测试类现在都在“工作”,但我想将它们合并到 InterfaceAAIGroupControllerTest 类中,但不知道如何在 PowerMock 中使用 Mockito。对于界面,我使用
groupi = PowerMockito.spy(new AAIGroupController());
对于我使用的另一个测试
@Mock private XMLConfiguration config;
@InjectMocks AAIGroupController groupi;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
对于代码:
界面:
public interface IAAIGroupController {
/**
* Appends a new group entry
*/
public void appendGroup();
/**
* checks if a given account is a possix account
*
* @param elUser the user object to check
* @return true if is posix, otherwise false
* @throws ConfigurationException
*/
public boolean isPosixAccount(ELUser elUser)
...
实施
@Override
public void appendGroup() {
try {
config.addProperty("ldapGroup(-1)",
List<SubnodeConfiguration> ldapGroups = config.configurationsAt("ldapGroup");
SubnodeConfiguration sn = ldapGroups.get(ldapGroups.size()-1);
try {
sn.addProperty("script(-1)", null);
// TODO Configuration
} catch (Exception e) {
sn.addProperty("script(-1)", "default.sh");
}
config.save();
} catch (ConfigurationException ex) {
LOGGER.log(Level.SEVERE, ex.getMessage());
}
}
@Override
public boolean isPosixAccount(final ELUser elUser) throws ConfigurationException {
SubnodeConfiguration ldapGroup = getLdapGroupNodeFromGroupConfigFile(elUser);
String posix = ldapGroup.getString("[@posix]");
if (posix == null || posix.isEmpty() || posix.equalsIgnoreCase("true")) {
return true;
} else if (posix.equalsIgnoreCase("false")) {
return false;
} else {
throw new ConfigurationException("posix attribute is not set properly!");
}
}
接口测试代码,暂时不能很好地处理异常,将在它工作时修复它。我正在使用 PowerMock,因为我必须在实现中调用私有方法。我不知道我是否可以通过这种方式很好地测试接口。
@RunWith(PowerMockRunner.class)
@PrepareForTest(AAIGroupController.class)
public class InterfaceAAIGroupControllerTest {
public IAAIGroupController iaigroupi;
public AAIGroupController groupi;
public XMLConfiguration config;
@Before
public void setUp() {
groupi = PowerMockito.spy(new AAIGroupController());
config = Whitebox.getInternalState(groupi, "config");
iaigroupi = groupi;
}
@Test
public void isPosixAccount_True() {
try {
SubnodeConfiguration sn = mock(SubnodeConfiguration.class);
when(iaigroupi, method(AAIGroupController.class, "getLdapGroupNodeFromGroupConfigFile", ELUser.class))
.withArguments(any(ELUser.class))
.thenReturn(sn);
assertTrue(iaigroupi.isPosixAccount(new ELUserAAI(null, true, false)));
} catch (ConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
实现的测试代码,这里我使用 Mockito 来模拟一个私有字段,该字段在代码中使用但从未由构造函数或方法设置。
@RunWith(MockitoJUnitRunner.class)
public class AAIGroupControllerTest {
@Mock private XMLConfiguration config;
@InjectMocks AAIGroupController groupi;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
public void appendGroupTest() {
List<SubnodeConfiguration> ldapGroups = mock(List.class);
SubnodeConfiguration sn = mock(SubnodeConfiguration.class);
given(config.configurationsAt(anyString())).willReturn(ldapGroups);
given(ldapGroups.size()).willReturn(11);
given(ldapGroups.get(ldapGroups.size()-1)).willReturn(sn);
groupi.appendGroup();
verify(sn).addProperty("script(-1)", null);
}
}
我现在的问题是,我可以像我一样测试一个接口吗?tbh 似乎不是一个很好的解决方案。参数化似乎没有必要,因为总是只有一个实现,我不知道如何使用两个 Runners。另一件事是,我如何使用上一个示例中的测试代码,我在其中模拟私有字段“config”,在 PowerMock 测试类中?我不知道如何正确模拟私有字段并在从中调用方法时更改其行为。
在此先感谢您的每一个提示!