继承能够访问父类私有字段
首先,让我大声说一下,您需要将代码设计为可测试的,以便通过公共方法测试私有字段。
但是,(“ buts”是人们仍在编程而不是计算机本身的原因,所以在这里很高兴)有时您想要并且应该更改一些私有字段以测试所有可能的边界。
通常,可以通过公共获取器和设置器或使用类构造函数来修改私有字段,在这种情况下,测试很容易创建并且每个人都很高兴。
但是,当您使用诸如Spring之类的外部框架时,可能无法控制注入的私有字段。
我已经在上一篇文章中解释了如何在测试中模拟spring组件,而无需维护和创建即席测试spring configuraitons ,这里我将向您展示如何为测试修改私有变量。
让我们说一下代码:
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.google.common.collect.ImmutableSet;
@Service
public class SomeService {@Value("${whitelist.api.users:A,B,C}")private String apiUsers;private ImmutableSet<String> acceptableAPIBUsers;@PostConstructpublic void init() {acceptableAPIBUsers = ImmutableSet.copyOf(apiUsers.replaceAll(" ", "").split(","));}public boolean isAnAcceptableUser(String user) {return user == null ? false : acceptableAPIBUsers.contains(user.toUpperCase());}
}
我们无法控制apiUsers字符串,因此我们有几个简单的选项,一个是为测试创建一个Spring配置,修改Spring上下文并模拟该属性,两个是创建一个setter来更改测试中的属性。
我不鼓励只为您的测试创建公共评估者,这会使其他人在查看您的代码以及为测试创建和维护Spring配置时感到困惑。
我知道您在想什么:“如果以上任何一项我都做不到,我将被解雇,我的女朋友会离开我,我的生活已经结束”,但您不用担心,我在这里向您展示另外的选择!
您可以使用静态方法创建groovy类,以评估测试中的私有字段:
import groovy.transform.CompileStatic
@CompileStatic
class SomeServiceAccessor {public static void setApiUsers(SomeService someService,String apiUsers){someService.@apiUsers = apiUsers}
}
并在单元测试中使用它:
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import org.junit.Before;
import org.junit.Test;
public class SomeServiceTest {private SomeService service;@Beforepublic void setUp() {service = new SomeSercvice();SomeSercviceAccessor.setApiUsers(service, "pippo,pluto,bungabunga");service.init();}@Testpublic void testIsNotApiUser() {assertThat(service.isAnRTBUser(""), is(false));assertThat(service.isAnRTBUser(null), is(false));assertThat(service.isAnRTBUser("random"), is(false));}@Testpublic void testIsRTBUser() {assertThat(service.isAnRTBUser("pippo"), is(true));assertThat(service.isAnRTBUser("PIPPO"), is(true));assertThat(service.isAnRTBUser("pluto"), is(true));assertThat(service.isAnRTBUser("bungabunga"), is(true));}
}
当然,您可以在Java中执行相同的操作,以通过反射来更改字段的可见性,但我认为常规解决方案可以是一种更干净,更轻松的方法。
现在,我将根据以下建议完成这篇文章:
除非您确实真的需要修改私有变量以对类进行单元测试,否则请不要使用此解决方案!
翻译自: https://www.javacodegeeks.com/2014/02/access-private-fields-in-unit-tests.html
继承能够访问父类私有字段