编辑:用较短的方式改写问题。谢谢你指出这一点!:(
我需要编写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 Class中,但不知道如何在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);
}
}
我现在的问题是,我能像以前那样测试接口吗?这似乎不是一个好的解决方案。参数化似乎没有必要,因为永远只有一个实现,而我不知道如何使用两个Runner。。另一件事是,我如何使用上一个例子中的测试代码,在PowerMock测试类中模拟私有字段"config"?我不知道如何正确地模拟私有字段,并在从中调用方法时改变它的行为
提前感谢您的每一条建议!
阅读本文时会想到三个想法:
- 你真的需要发布那么多代码吗?你真的希望我们能全部阅读吗?你的问题很含糊,很难理解。考虑一次问一个问题
- 你不测试接口。一个接口没有任何代码,有什么可以测试的
- 如果您使用
PowerMock
进行嘲讽,请不要在同一测试中也使用Mockito
。根据您的要求使用其中一个
要设置专用字段,请提供一个setter(可能在默认范围内(或使用反射(如ReflectionTestUtils(进行设置。