"Mock" 固定参数的方法
"Mock" method with fixed parameters
我的项目中有一个 "Mailer" class(当然会发送电子邮件)。为了进行测试,我希望 Mailer#send(String toAddress)
的每个调用都替换为 Mailer#send("mail@example.com")
.
所以像这样:
@RunWith(PowerMockRunner.class)
@PrepareForTest({ClassCallingMailer.class})
public class TestClass {
@Test
public void testMethod() {
Mailer mailerMock = mock(Mailer.class);
// this is where the magic happens; replace any toAddress with fixed email address
when(mailerMock.send(any(String.class))).thenReturn(mailerMock.send("mail@example.com"));
try {
whenNew(Mailer.class).withAnyArguments().thenReturn(mailerMock);
} catch (Exception e) {
e.printStackTrace();
}
ClassCallingMailer someClass = new ClassCallingMailer();
assertTrue(someClass.methodSendingMail());
}
}
这段代码显然是行不通的,但是可以通过某种方式实现吗?
也许这是一个完全错误的方法?
谢谢。
更新
我不太确定这有多好,但它确实有效:
// ClassCallingMailer (no changes, just for completeness)
public class ClassCallingMailer {
public boolean methodSendingMail() {
Mailer mail = new Mailer();
return mail.send(someEmailAddress);
}
}
// TestMailer (new class)
public class TestMailer extends Mailer {
// add all constructors from Mailer
@Override
public boolean send(String to) {
return super.send("mail@example.com");
}
}
// TestClass (with changes)
@RunWith(PowerMockRunner.class)
@PrepareForTest({ClassCallingMailer.class})
public class TestClass {
@Test
public void testMethod() {
// changed mock to spy and replaced Mailer with TestMailer
Mailer mailerMock = spy(TestMailer.class);
// removed "when(...).thenReturn(...)"
try {
whenNew(Mailer.class).withAnyArguments().thenReturn(mailerMock);
} catch (Exception e) {
e.printStackTrace();
}
ClassCallingMailer someClass = new ClassCallingMailer();
assertTrue(someClass.methodSendingMail());
}
}
如果你只想实现这种行为,我建议不要通过模拟来实现。
您可以扩展您的 Mailer
class 以拥有一些 TestMailer
,您可以在其中执行以下操作:
@Override
public void send(String toAddress){
super.send("mail@example.com");
}
基本上,您覆盖了 Mailer
的原始发送并使用预定义地址调用它。
您可以在测试中使用这个新子class。
我的项目中有一个 "Mailer" class(当然会发送电子邮件)。为了进行测试,我希望 Mailer#send(String toAddress)
的每个调用都替换为 Mailer#send("mail@example.com")
.
所以像这样:
@RunWith(PowerMockRunner.class)
@PrepareForTest({ClassCallingMailer.class})
public class TestClass {
@Test
public void testMethod() {
Mailer mailerMock = mock(Mailer.class);
// this is where the magic happens; replace any toAddress with fixed email address
when(mailerMock.send(any(String.class))).thenReturn(mailerMock.send("mail@example.com"));
try {
whenNew(Mailer.class).withAnyArguments().thenReturn(mailerMock);
} catch (Exception e) {
e.printStackTrace();
}
ClassCallingMailer someClass = new ClassCallingMailer();
assertTrue(someClass.methodSendingMail());
}
}
这段代码显然是行不通的,但是可以通过某种方式实现吗? 也许这是一个完全错误的方法?
谢谢。
更新
我不太确定这有多好,但它确实有效:
// ClassCallingMailer (no changes, just for completeness)
public class ClassCallingMailer {
public boolean methodSendingMail() {
Mailer mail = new Mailer();
return mail.send(someEmailAddress);
}
}
// TestMailer (new class)
public class TestMailer extends Mailer {
// add all constructors from Mailer
@Override
public boolean send(String to) {
return super.send("mail@example.com");
}
}
// TestClass (with changes)
@RunWith(PowerMockRunner.class)
@PrepareForTest({ClassCallingMailer.class})
public class TestClass {
@Test
public void testMethod() {
// changed mock to spy and replaced Mailer with TestMailer
Mailer mailerMock = spy(TestMailer.class);
// removed "when(...).thenReturn(...)"
try {
whenNew(Mailer.class).withAnyArguments().thenReturn(mailerMock);
} catch (Exception e) {
e.printStackTrace();
}
ClassCallingMailer someClass = new ClassCallingMailer();
assertTrue(someClass.methodSendingMail());
}
}
如果你只想实现这种行为,我建议不要通过模拟来实现。
您可以扩展您的 Mailer
class 以拥有一些 TestMailer
,您可以在其中执行以下操作:
@Override
public void send(String toAddress){
super.send("mail@example.com");
}
基本上,您覆盖了 Mailer
的原始发送并使用预定义地址调用它。
您可以在测试中使用这个新子class。