在模拟类中初始化私有字段

时间:2019-02-12 15:35:40

标签: java unit-testing junit mockito

我在我的课程中有一个私有字段,并且如果设置了某个标志并且如果映射包含某个值,则该方法会对其进行修改。我想测试该方法并查看结果。这是代码(为简洁起见,省略了不相关的字段和方法):

我的课程:

class UsersLoader {
   private Collection<User> users;
   private Map<Integer,Boolean> status;

   UsersLoader() {
      users = new ArrayList<>();
      status = new HashMap<>();
   }

   protected loadExternalUsers(boolean condition) {
      Collection<User> externalUsers = LoadUsersFromSomeExternalSource();
      if (condition && status.get(SOME_KEY)) {
         users.addAll(externalUsers);
      } else {
         /* do not modify my users */
      }
   }
}

我的测试:

import static org.mockito.Mockito.mock;

public class UsersLoaderTest {
   private UsersLoader loader;

   @Before
   public void setUp() {
      loader = mock(UsersLoader.class);
      doCallRealMethod().when(loader).loadExternalUsers(anyBoolean());
   }

   @Test
   public void testLoadingWhenFlagIsTrue {
      Collection<User> users = loader.loadExternalUsers(true);
      assertThat(users.size() == 1);
   }

   @Test
   public void testLoadingWhenFlagIsFalse {
      Collection<User> users = loader.loadExternalUsers(false);
      assertThat(users.size() == 0);
   }

}

运行测试时,在NullPointerException类中得到UsersLoader,与IF子句一致,该子句检查status.get(SOME_KEY)。即使我解决了该问题,下一个NPE也会在下面一行,因为我的users为空。如何在模拟的类中初始化私有字段,以便可以使用它们?我可以创建一个getter和setter并模拟它们,但是随后整个测试就失去了意义。

3 个答案:

答案 0 :(得分:3)

您可以使用间谍代替模拟游戏。

这将触发构造函数,并为私有变量分配一个空列表,从而使NPE转义:

private UsersLoader loader;

@Before
public void setUp() {
  loader = spy(new UsersLoader());
}

现在您无需拨打电话:

  doCallRealMethod().when(loader).loadExternalUsers(anyBoolean());

请记住,您需要模拟不需要在实现时触发的任何方法。

答案 1 :(得分:1)

首先,将初始化移动到字段的声明:

private Collection<User> users = new ArrayList<>();

然后,您可以使用自己的模拟程序注入该字段:

@RunWith(MockitoJUnitRunner.class)
class UsersLoaderTest {
       @Mock
       private Collection<User> users;
       @InjectMocks
       private UsersLoader loader;
}

,然后验证是否与您期望的用户一起调用users.add()

答案 2 :(得分:1)

不要模拟UsersLoader.class,这是包含要测试的方法的类。创建模拟时,将不会实现模拟的类,而是可以模拟该类的功能。宁可监视它,也可以仅实例化并提供检查功能的手写检查。在后一种情况下,您根本不需要Mockito。因此,您可以对其进行监视并使用嘲笑功能来测试功能