1

编辑:以更短的方式重写了问题。感谢您指出了这一点!:)

我需要编写 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 测试类中?我不知道如何正确模拟私有字段并在从中调用方法时更改其行为。

在此先感谢您的每一个提示!

4

1 回答 1

0

读到这里,我会想到三个想法:

  • 您真的需要发布那么多代码吗?您真的希望我们阅读所有内容吗?你的问题很模糊,很难理解。考虑一次问一个问题。
  • 你不测试接口。一个接口没有任何代码,有什么要测试的?
  • 如果您PowerMock用于模拟,请不要Mockito在同一测试中使用。根据您的要求使用一种或另一种

要设置私有字段,请提供一个设置器(可能在默认范围内)或使用反射(例如 ReflectionTestUtils)来设置它。

于 2013-05-07T15:22:25.110 回答