我有一个如下所示的 Java 类:
public class MyClass {
/** Database Connection. */
private dbCon;
public MyClass() {
dbCon = ...
}
public void doSomethingWith(MyData data) {
data = convertData(data);
dbCon.storeData(data);
}
private MyData convertData(MyData data) {
// Some complex logic...
return data;
}
}
Run Code Online (Sandbox Code Playgroud)
由于这个类的真正逻辑在于convertData()方法,所以我想为这个方法编写一个单元测试。所以我读了这篇文章
很多人说需要测试私有方法是一种设计味道。怎样才能做得更好呢?
我看到两种方法:
convertData()使用公共 api 将方法提取到某个实用程序类中。但我认为这也是一种不好的做法,因为此类实用程序类将违反单一责任原则,除非我创建大量可能只有一两个方法的实用程序类。
编写第二个允许注入的构造函数dbCon,这允许我注入数据库连接的模拟版本并针对公共doSomething()方法运行测试。这将是我首选的方法,但也有关于模拟的需要如何也是一种代码味道的讨论。
对于这个问题有什么最佳实践吗?
我在这个答案中看到,对于Java,您可以在单元测试中将私有方法的可见性设置为"true",以便测试该方法.有没有这样的东西可用于VBA,所以我可以使用RD-VBA对私有方法进行单元测试?
如果没有,并且我有一个类在三个私有方法中计算出一些逻辑并将其返回给返回值,我注定只给出一个输入值并测试返回值,而不能测试三个私有方法在两者之间做升降机吗?
我有一个构造函数,它调用两个方法。它们都是无效的,我只是想验证它们是否被调用。
文件
public class Foo {
public Foo(String name, Object obj) {
init(name);
doSomething(obj);
}
}
Run Code Online (Sandbox Code Playgroud)
测试文件
@Test
public void constructor_test throws Exception {
Foo foo = Mockito.mock(Foo.class);
PowerMockito.whenNew(Foo.class).withAnyArguments().thenReturn(foo);
Foo f = new Foo("name");
verify(f).init(Mockito.anyString());
verify(f).doSomething(Mockito.any(Object.class));
}
Run Code Online (Sandbox Code Playgroud)
单元测试失败并显示一条消息,指出与模拟foo.init() 的交互为零;.
如何验证构造函数中的方法调用?
我读了一下关于TDD和测试的一般情况,并决定我想尝试一下.
在找到如何在Android Studio中运行测试之后,我意识到我的大多数方法都是私有的(因此直接测试它们是错误的,因为这个链接:我如何测试具有私有方法,字段或内部类的类?).
是什么赋予了?这是一种设计气味吗?我应该以某种方式重构吗?
鉴于我应该只能在失败的测试后编写代码,我将如何处理那些公共方法很少的类,比如我的大部分活动?我错过了什么?
请记住,我是新手.
我想测试我的方法在无法模拟的同一类中调用了另一个方法。
例:
public void methodToTest(){
//other stuff to test that can be mocked
someClassICanMock.doSomething();
//method within same class that cannot be mocked
methodFromSameClassIWantToVerify();
}
Run Code Online (Sandbox Code Playgroud)
我如何使用a verify来检查我的测试方法methodFromSameClassIWantToVerify();?
编辑:不是重复的,因为我专门指的是如何使用Mockito对此进行测试。
我正在学习Scala并编写了Email类似于以下内容的类:
class Email(emailConfigName: String) {
private val emailConfig = ConfigFactory.load(emailConfigName) getConfig ("email")
def notifySupportForTenant(symbolicName: String) {
val emailMessage: Message = constructEmailMessage(symbolicName)
Transport.send(emailMessage)
}
def constructEmailMessage(symbolicName: String): Message = {
val message = createMessage(emailConfig getString ("shn.mail.smtp.host"))
message setFrom (new InternetAddress(emailConfig getString ("shn.mail.from")))
// todo: should come from API (sent by client)
message setSentDate (new Date())
message setSubject (emailConfig getString ("shn.mail.subject") replace("TENANT_ID", symbolicName))
message setContent(emailConfig getString ("shn.mail.body"), "text/html")
message.setRecipients(Message.RecipientType.TO, getMessageRecipients(emailConfig getString ("shn.mail.recipient")))
message
}
private def createMessage(smtpHost: String): Message = …Run Code Online (Sandbox Code Playgroud) 作为副本提出的解决方案不是 PowerMockito 解决方案,因此不能回答这个问题。此外,这个问题在下面得到了合理的回答。
IDK 是否是重复的,但如果是重复的,我肯定找不到相关项目。我一直期待这真的很简单,因为反射很简单,但我宁愿使用正确的工具来做。
说明:遗留代码。没有吸气剂/二传手。
为此使用 Whitebox 是否正确?我认为它是“Off Limits”,即内部 API 的一部分?……还是严格意义上的 Mockito?
unit-testing ×6
java ×5
junit ×4
mockito ×2
powermock ×2
android ×1
method-call ×1
powermockito ×1
rubberduck ×1
scala ×1
scalatest ×1
tdd ×1
vba ×1
verify ×1