gpt4 book ai didi

java - 如何测试一个方法和它的两个助手之间的交互?

转载 作者:行者123 更新时间:2023-11-30 08:23:45 25 4
gpt4 key购买 nike

我的 Java 代码结构如下:

public MyClass {
// some class variables
...
private void process() {
private MyObject obj;
...
obj = createHelper();
...
messageHelper(obj, "One of several possible strings");
...
messageHelper(obj, "Another call with a different string");
...
}

private MyObject createHelper {
MyObject obj = new MyObject();
// some Setter calls
...
return obj;
}

private void messageHelper (MyOject obj, String message) {
...
}

}

我想测试,基于属性 obj(我想指定),messageHelper() 接收正确的字符串。换句话说,我需要控制一种方法的结果并有权访问另一种方法的参数。

我仍然对所有这些 Mock/Stub/Spy 东西感到不安。

在我看来,我需要在 MyClassSpystub CreateHelper() 带有“手动”创建的对象,但不确定要拦截 messageHelper() 的调用参数。

我还注意到 Wiki使用 Spies 的注意事项:

Think twice before using this feature. It might be better to change the design of the code under specification.

那么 Spocky 完成任务的合适方法是什么?

稍微重构的代码: (5/5/14)

public MyClass {
// some class variables
private messageSevice = new messageService();
...
private void process() {
private MyObject obj;
...
obj = new MyObject(parameters ...);
...
if (someCondition) {
messageService.produceMessageOne(obj);
}
...
if (otherCondition) {
messageService.produceMessageTwo(obj);
{
...
}

}

public class MessageService implements IMessageService {

private final static MSG_ONE = "...";
private final static MSG_TWO = "...";
...

public void produceMessageOne(MyObject obj) {
produceMessage(obj, MSG_ONE);
...
}
public void produceMessageOne(MyObject obj) {
produceMessage(obj, MSG_TWO);
}

private void produceMessage(MyObject obj, String message) {
...
}
}

如果有人建议使用 Spock 进行测试的方式,我将不胜感激。

最佳答案

您所指的警告是正确的。可测试代码与良好设计之间存在非常好的相关性(我建议观看 Michael Feathers 的讲座以了解原因 http://www.youtube.com/watch?v=4cVZvoFGJTU)。

使用 spy 往往会引起设计问题,因为它通常是由于无法使用常规模拟和 stub 而引起的。

从你的例子中很难预测,因为你显然使用了假名,但 MyClass 类的设计似乎违反了单一责任原则( http://en.wikipedia.org/wiki/Single_responsibility_principle ),因为它执行处理、创建和消息传递(3 个职责)。

如果您愿意更改您的设计,以便处理类 (MyClass) 将只进行处理,您将提供另一个进行创建的类 (MyObjectFactory),以及另一个通过构造函数、setter 方法或依赖注入(inject)执行消息传递的类 (MyObjectMessager)。

使用这种新设计,您可以创建您正在测试的类 (MyClass) 的实例,并将工厂类和消息传递类的模拟对象传递给它。然后您就可以在两者上验证您想要的任何内容。

看看这个例子(使用 Mockito):

public class MyClassTest {
@Test
public void testThatProcessingMessagesCorrectly() {
MyObject object = mock(MyObject.class);
MyObjectFactory factory = mock(MyObjectFactory.class);
when(factory.createMyObject()).thenReturn(object);
MyObjectMessager messager = mock(MyObjectMessager.class);

MyClass processor = new MyClass(factory, messager);
processor.process();

verify(factory).createMyObject();
verify(messager).message(EXPECTED_MESSAGE_1);
verify(messager).message(EXPECTED_MESSAGE_2);
...
verify(messager).message(EXPECTED_MESSAGE_N);
}

...
}

这是一个 Spock 示例(未经测试,使用前仔细检查...):

public class MyClassSpec extends Specification {
def "check that the right messages are produced with the expected object"() {
given:
def messageService = Mock(IMessageService)
def testedInstance = new MyClass()

testedInstance.setMessageService(messageService)

when:
testedInstance.process()

then:
1 * messageService.produceMessageOne(_)
1 * messageService.produceMessageTwo(_)
}
}

关于java - 如何测试一个方法和它的两个助手之间的交互?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23436130/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com