我有一个私有方法的伴侣对象,如下所示:
package com.example.people
class Person(val age: Int)
object Person {
private def transform(p: Person): Person = new Person(p.age + 1)
}
Run Code Online (Sandbox Code Playgroud)
我想测试这个方法,例如:
class PersonSpec extends FlatSpec {
"A Person" should "transform correctly" in {
val p1 = new Person(1)
val p2 = Person.transform(p1) // doesn't compile, because transform is private!
assert( p2 === new Person(2) )
}
}
Run Code Online (Sandbox Code Playgroud)
有关测试代码访问私有方法的任何帮助吗?
实际上,正如它所写,我可能能够创建一个子类Person,但如果Person被声明为final或sealed?
谢谢!
我对单元测试很新,我有点困惑.
我试图在一个名为C++的类上进行单元测试(使用Boost单元测试框架)VariableImpl.这是详细信息.
class Variable
{
public:
void UpdateStatistics (void) {
// compute mean based on m_val and update m_mean;
OtherClass::SendData (m_mean);
m_val.clear ();
}
virtual void RecordData (double) = 0;
protected:
std::vector<double> m_val;
private:
double m_mean;
};
class VariableImpl : public Variable
{
public:
virtual void RecordData (double d) {
// put data in m_val
}
};
Run Code Online (Sandbox Code Playgroud)
我的问题是如何检查均值是否正确计算?注意1)m_mean受保护,2)UpdateStatistics调用另一个类的方法,然后清除向量.
我能看到的唯一方法是添加一个getter(例如GetMean),但我根本不喜欢这个解决方案,也不认为它是最优雅的.
我应该怎么做?
如果我要测试私有方法而不是私有变量,我该怎么办?
TIA,
JIR
我有一个Singleton/Factory对象,我想编写一个JUnit测试.Factory方法根据类路径上属性文件中的类名决定实例化哪个实现类.如果未找到属性文件,或者属性文件不包含classname键,则该类将实例化默认实现类.
由于工厂保持Singleton的静态实例在实例化后使用,为了能够在Factory方法中测试"故障转移"逻辑,我需要在不同的类加载器中运行每个测试方法.
有没有办法使用JUnit(或其他单元测试包)来做到这一点?
编辑:这是一些正在使用的Factory代码:
private static MyClass myClassImpl = instantiateMyClass();
private static MyClass instantiateMyClass() {
MyClass newMyClass = null;
String className = null;
try {
Properties props = getProperties();
className = props.getProperty(PROPERTY_CLASSNAME_KEY);
if (className == null) {
log.warn("instantiateMyClass: Property [" + PROPERTY_CLASSNAME_KEY
+ "] not found in properties, using default MyClass class [" + DEFAULT_CLASSNAME + "]");
className = DEFAULT_CLASSNAME;
}
Class MyClassClass = Class.forName(className);
Object MyClassObj = MyClassClass.newInstance();
if (MyClassObj instanceof MyClass) {
newMyClass = (MyClass) MyClassObj;
}
} …Run Code Online (Sandbox Code Playgroud) 我知道我们可以通过反射来访问私有构造函数@Sanjay T. Sharma在他的问题回答中提到:"instanceof Void"总是返回false吗?
你可以使用反射访问私有 - 方法,构造函数,数据成员,一切.
我有一个独立的单身人士,成功通过了测试.但是通过一组测试,这会失败,因为一旦定义了单例,它就不允许重置实例.
关于如何解决这个问题的任何想法?
可能重复: 单元测试私有方法的最佳方法是什么?
我是初学程序员,我不知道如何编写一个结构良好的单元测试应用程序.我想编写能够在之后添加有效单元测试的应用程序.
问题在于private方法 - 它们无法在类之外进行测试.
我应该改变是所有的方法解决这个问题private来protected,让测试类扩展源类?或者有更好的解决方案吗?
我的解决方案(private splitLetters => protected splitLetters)将如下工作:
来源类:
class MyClass{
protected splitLetters(int num){
return num+2;
}
}
Run Code Online (Sandbox Code Playgroud)
测试类:
class Test_MyClass extend MyClass{
public splitLettersTest(){
for(int i=0;i<100;i++){
System.println(parent.splitLetters(i));
}
}
}
Run Code Online (Sandbox Code Playgroud)
解决方案:
不测试私有方法 - 有时私有方法正在执行非常复杂的任务,应该进行非常好的测试,我们不希望该用户可以访问这些方法.很快,解决方案就是将私有方法改为受保护.
嵌套类测试方法 - 有问题,因为QA在源代码中进行了更改
反思 - 如果这可以调用私有方法,它看起来像一个很好的解决方案http://www.artima.com/suiterunner/private3.html (我应该学习更多来理解反射.我不明白反射如何做如果我们可以从另一个类调用私有方法,那就不要破坏拥有公共和私有方法的所有想法.)
没有定义私有方法(正如我在我的解决方案中所示) - 有问题,因为有时我们必须定义私有方法.
在许多应用程序中,我经常使用算法来利用专用的子算法(或简单明确定义的代码片段).
直到现在,当我编写主算法时,我为每个子算法创建了一个私有方法,如下例所示(OldStyle):
public class OldStyle {
public int mainAlg() {
int x = subAlg01();
int y = subAlg02();
int z = x * y;
return z;
}
private int subAlg01() {
return 3;
}
private int subAlg02() {
return 5;
}
}
Run Code Online (Sandbox Code Playgroud)
这很好但我不喜欢增加方法(subAlg01和subAlg02),即使是私有的,也只使用一种方法(mainAlg).
最近我发现使用了本地内部类,现在我的例子是(NewStyle):
public class NewStyle {
public int mainAlg() {
class Nested {
public int subAlg01() {
return 3;
}
public int subAlg02() {
return 5;
}
}
Nested n = new Nested();
int x = n.subAlg01();
int …Run Code Online (Sandbox Code Playgroud) 我正在使用Mockito 1.9.5.如何模拟受保护方法返回的内容?我有这种受保护的方法......
protected JSONObject myMethod(final String param1, final String param2)
{
…
}
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试在JUnit中执行此操作时:
final MyService mymock = Mockito.mock(MyService.class, Mockito.CALLS_REAL_METHODS);
final String pararm1 = “param1”;
Mockito.doReturn(myData).when(mymock).myMethod(param1, param2);
Run Code Online (Sandbox Code Playgroud)
在最后一行,我得到一个编译错误"方法'myMethod'不可见."我如何使用Mockito来模拟受保护的方法?如果这是答案,我愿意升级我的版本.
当使用Mockito 1.9.x时,我一直Whitebox用来设置字段值以"注入"模拟.以下示例:
@Before
public void setUp() {
eventHandler = new ProcessEventHandler();
securityService = new SecurityServiceMock();
registrationService = mock(RegistrationService.class);
Whitebox.setInternalState(eventHandler, "registrationService", registrationService);
Whitebox.setInternalState(eventHandler, "securityService", securityService);
}
Run Code Online (Sandbox Code Playgroud)
我真的很喜欢这种方法,但是现在我尝试升级到Mockito 2.2.7我注意到(或者更确切地说,我的IDE注意并告诉了我很多次),在Mockito中找不到Whitebox.
我找到了一个可以替代的替代方案,也就是说 org.powermock.reflect.Whitebox,问题在于我得到另一个依赖(Powermock),只是为了使用Whitebox.
Powermock还有一个名为的类Whitebox,但遗憾的是它看起来好像不能用Mockito 2.2.x
Mockito有什么好的替代方案可以用来手动"注入"字段,现在Whitebox已经不再可用了吗?
我在回复@JeffBowman的帖子时写了一篇评论.简而言之,我选择复制WhiteBox的代码,并使用它,因为它在大多数测试用例中使用,并且该类与其他类没有依赖关系.这是解决这个问题的最快途径.
注意 @bcody建议的解决方案是一个更好的选择,如果你使用spring,它不会为你维护额外的代码.我得到的信息很晚了:(
今天我与一位同事讨论了是否要测试是否在课堂上测试私人成员或私人状态.他几乎让我相信为什么它有意义.这个问题的目的不是复制已经存在的关于测试私有成员的性质和原因的StackOverflow问题,例如:将单元测试作为正在测试的类的朋友有什么问题?
在我看来,同事的建议有点脆弱,将朋友声明介绍给单元测试实现课程.在我看来,这是一个禁忌,因为我们将测试代码的一些依赖性引入测试代码,而测试代码已经依赖于测试代码=>循环依赖.即使像重命名测试类这样无辜的事情也会导致破坏单元测试并在测试代码中强制执行代码更改.
我想请C++专家来判断另一个提案,它依赖于我们被允许专门化模板功能的事实.想象一下班级:
// tested_class.h
struct tested_class
{
tested_class(int i) : i_(i) {}
//some function which do complex things with i
// and sometimes return a result
private:
int i_;
};
Run Code Online (Sandbox Code Playgroud)
我不喜欢让i_的吸气剂让它变得可测试.所以我的提议是类中的'test_backdoor'函数模板声明:
// tested_class.h
struct tested_class
{
explicit
tested_class(int i=0) : i_(i) {}
template<class Ctx>
static void test_backdoor(Ctx& ctx);
//some function which do complex things with i
// and sometimes return a result
private:
int i_;
};
Run Code Online (Sandbox Code Playgroud)
通过添加这个函数,我们可以使类的私有成员可测试.注意,不依赖于单元测试类,也不依赖于模板函数实现.在此示例中,单元测试实现使用Boost Test框架.
// tested_class_test.cpp
namespace
{
struct ctor_test_context
{
tested_class& tc_;
int …Run Code Online (Sandbox Code Playgroud)