Junit Interface Powermock

时间:2013-05-07 13:58:13

标签: junit mockito powermock

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

我需要编写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测试。这是无意义的,因为实现接口的类已经过测试。如果不是,它会有什么好的做法?

提前致谢!

旧问题,可以完全跳过。我只是让它来理解已经给出的答案。

我必须为Interfaces编写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);
    }

}

我现在的问题是,我可以像我一样测试界面吗?似乎不是一个很好的解决方案。参数化似乎是不必要的,因为总会有一个实现,我不知道如何使用两个Runners .. 另一件事是,我如何使用上一个示例中的测试代码,我在PowerMock测试类中模拟私有字段“config”?我不知道如何正确地模拟私有字段并在从它调用方法时改变它的行为。

提前感谢您的每一个提示!

1 个答案:

答案 0 :(得分:0)

阅读本文时会想到三个想法:

  • 你真的需要发布那么多代码,你真的希望我们能够全部阅读吗?你的问题很模糊,很难理解。考虑一次提出一个问题。
  • 您不测试接口。一个接口没有任何代码,有什么可以测试?
  • 如果您使用PowerMock进行模拟,请不要在同一测试中使用Mockito。使用您的要求中定义的一个或另一个

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