我需要测试一些遗留代码,这些代码在a方法调用中使用了单例。测试的目的是确保类sunder测试对singletons方法进行调用。我在SO上看到过类似的问题,但所有的答案都需要其他依赖项(不同的测试框架)--不幸的是,我仅限于使用Mockito和JUnit,但对于这样流行的框架,这应该是完全可能的。
单身人士:
public class FormatterService {
private static FormatterService INSTANCE;
private FormatterService() {
}
public static FormatterService getInstance() {
if (INSTANCE == null) {
INSTANCE = new FormatterService();
}
return INSTANCE;
}
public String formatTachoIcon() {
return "URL";
}
}
正在测试的类:
public class DriverSnapshotHandler {
public String getImageURL() {
return FormatterService.getInstance().formatTachoIcon();
}
}
单元测试:
public class TestDriverSnapshotHandler {
private FormatterService formatter;
@Before
public void setUp() {
formatter = mock(FormatterService.class);
when(FormatterService.getInstance()).thenReturn(formatter);
when(formatter.formatTachoIcon()).thenReturn("MockedURL");
}
@Test
public void testFormatterServiceIsCalled() {
DriverSnapshotHandler handler = new DriverSnapshotHandler();
handler.getImageURL();
verify(formatter, atLeastOnce()).formatTachoIcon();
}
}
这个想法是配置可怕的单例的预期行为,因为被测试的类将调用它的getInstance方法,然后调用formatTachoIcon方法。不幸的是,这将失败,并出现错误消息:
when() requires an argument which has to be 'a method call on a mock'.
您的getInstance方法是静态的,因此不能使用mockito进行嘲弄。http://cube-drone.com/media/optimized/172.png。您可能需要使用PowerMockito来执行此操作。虽然我不建议这样做。我将通过依赖注入测试DriverSnapshotHandler:
public class DriverSnapshotHandler {
private FormatterService formatterService;
public DriverSnapshotHandler(FormatterService formatterService) {
this.formatterService = formatterService;
}
public String getImageURL() {
return formatterService.formatTachoIcon();
}
}
单元测试:
public class TestDriverSnapshotHandler {
private FormatterService formatter;
@Before
public void setUp() {
formatter = mock(FormatterService.class);
when(formatter.formatTachoIcon()).thenReturn("MockedURL");
}
@Test
public void testFormatterServiceIsCalled() {
DriverSnapshotHandler handler = new DriverSnapshotHandler(formatter);
handler.getImageURL();
verify(formatter, times(1)).formatTachoIcon();
}
}
您可能希望在@after方法中将mock设置为null。这是IMHO的清洁解决方案。
我认为这是可能的。请参阅如何测试单例的示例
测试前:
@Before
public void setUp() {
formatter = mock(FormatterService.class);
setMock(formatter);
when(formatter.formatTachoIcon()).thenReturn(MOCKED_URL);
}
private void setMock(FormatterService mock) {
try {
Field instance = FormatterService.class.getDeclaredField("instance");
instance.setAccessible(true);
instance.set(instance, mock);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
测试之后--清理类很重要,因为其他测试会与模拟实例混淆。
@After
public void resetSingleton() throws Exception {
Field instance = FormatterService.class.getDeclaredField("instance");
instance.setAccessible(true);
instance.set(null, null);
}
测试:
@Test
public void testFormatterServiceIsCalled() {
DriverSnapshotHandler handler = new DriverSnapshotHandler();
String url = handler.getImageURL();
verify(formatter, atLeastOnce()).formatTachoIcon();
assertEquals(MOCKED_URL, url);
}
您的要求是不可能的,因为您的遗留代码依赖于静态方法getInstance()
,而Mockito不允许模拟静态方法,因此下面的行将不起作用
when(FormatterService.getInstance()).thenReturn(formatter);
有两种方法可以解决这个问题:
>
使用允许模拟静态方法的其他模拟工具,如PowerMock。
重构您的代码,这样您就不会依赖于静态方法。我能想到的实现这一点的最小侵入性的方法是向DriversNapShotHandler
中添加一个构造函数,该构造函数注入FormatterService
依赖项。这个构造函数将只在测试中使用,您的生产代码将继续使用真正的单例实例。
public static class DriverSnapshotHandler {
private final FormatterService formatter;
//used in production code
public DriverSnapshotHandler() {
this(FormatterService.getInstance());
}
//used for tests
DriverSnapshotHandler(FormatterService formatter) {
this.formatter = formatter;
}
public String getImageURL() {
return formatter.formatTachoIcon();
}
}
那么,您的测试应该是这样的:
FormatterService formatter = mock(FormatterService.class);
when(formatter.formatTachoIcon()).thenReturn("MockedURL");
DriverSnapshotHandler handler = new DriverSnapshotHandler(formatter);
handler.getImageURL();
verify(formatter, atLeastOnce()).formatTachoIcon();
我正在为类编写一个单元测试,该类如下所示: 我想编写一个简单的单元测试,它将方法存根(这样它就不会实际触发并命中数据库),但它允许我验证调用是否最终执行。Mockito似乎是这份工作的合适工具。 这似乎是一个很好的游戏计划(至少对我来说)。但当我实际编写代码时,在测试方法的第2行(行)出现以下编译器错误: 类型Mockito中的(T)不适用于参数(void)时的方法 我看到Mockito无法模拟返
在helper类的静态方法中调用时,它会抛出一个NPE。我所做的是嘲笑MarkupMaker和它的返回值(一个Markup实例)。最后,我希望调用标记实例的。无论我做什么-的调用都是抛出一个NPE。我找不到任何文档告诉我如何在spock中详细模拟方法调用值。 编辑:我添加了示例。的调用返回null,即使我在spock测试中对其进行了嘲弄。 test.groovy java(执行模拟对象的方法) j
正在测试的类: 下面是测试代码。我模拟了测试中的类class,并覆盖了方法getFruits的返回值。但是当我运行mock时,我没有得到预期的mock返回值。Easymock可以将返回值替换为被测试类的方法,如果这些方法是显式模拟的。当我模拟真实的对象方法时,如何获得模拟的返回值。
我必须测试一个用Spring注入两个映射的类。我想模拟两张地图。我使用模拟符号如下: 但我得到以下错误:
我正在尝试Mockito进行模拟和单元测试。 试图使用模拟autowired bean。但bean在运行时为空。 正在测试的类。 测试类: 错误: 我调试过,是因为(使用MockBean进行模拟,因为它是。) 这个代码有什么问题?
任何帮助都将得到高度赞赏。 提前致谢