Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/350.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 通过Mockito注入字符串_Java_Unit Testing_Mockito - Fatal编程技术网

Java 通过Mockito注入字符串

Java 通过Mockito注入字符串,java,unit-testing,mockito,Java,Unit Testing,Mockito,在测试BusinessFlow的类中,我有一些私有服务字段和一个javaString类型的私有字段 在我的测试课上我有 @RunWith(MockitoJUnitRunner.class) public class BusinessFlowTest { // How can I mock or spy this? private String code = "codeValue"; @Mock private Service1Api service1; @

在测试
BusinessFlow
的类中,我有一些私有服务字段和一个java
String
类型的私有字段

在我的测试课上我有

@RunWith(MockitoJUnitRunner.class)
public class BusinessFlowTest {
    // How can I mock or spy this?
    private String code = "codeValue";
    @Mock
    private Service1Api service1;
    @Mock
    private Service2Api service2;
    @InjectMocks
    private BusinessFlow flow;
    ...
}
@injectmock
@Mock
注释极大地创建了Mock和injectservice字段。但是当Mockito不允许为
final
类创建mock时,如何为
code
字段创建mock

我看到的一个选项是使用
CharSequence
接口而不是
String
字段类型,但它需要更改
BusinessFlow
类的代码,我不喜欢这种想法

更新:class
BusinessFlow
的定义如下

@Service
public class BusinessFlow {
    @Autowired
    @Qualifier(value = "clientCode")
    private String code;

    @Autowired
    private Service1Api service1;
    @Autowired
    private Service2Api service2;

    ...
}

出于某种原因,我们不使用Spring集成测试功能,也不想在不同类型的注入(例如,ctor注入)中返工
BusinessFlow

模拟的目的是模拟外部依赖,这些依赖要么过于禁止,无法在测试上下文中启动,要么没有必要这样做。您模拟服务和DAO层访问点,以确保您所做的只是一个单元测试

您想要做的是为您运行的每个测试更改此字段的值,独立于您的模拟。记住——这些模拟是外部依赖项。你可以很容易地控制进入课堂的字符串

有关测试中的示例:

@Test
public void testWithFoo() {
    // given
    flow.setValue("foo");

    // when
    // invoke a pertinent method

    // then
    // observe results
}

*:如果不能,这是一个很好的重构机会。

java.lang
包中模拟任何东西被认为是非常糟糕的做法。 此外,不建议在春季使用现场注入。 控制
Spring代码的最便宜的方法是重构类以使用构造函数注入

@Service
public class BusinessFlow {

    private String code;

    private Service1Api service1;

    private Service2Api service2;

    @Autowired
    public BusinessFlow(@Qualifier(value = "clientCode") String code,
                        Service1Api service1,
                        Service2Api service2) {
        this.code = code;
        this.service1 = service1;
        this.service2 = service2;
    }
}
这将不花费任何费用,您不必更改
BusinessFlow
类的客户机(只要它由Spring管理)。 现在您可以控制注入到类中的数据,而无需使用Spring测试特性

Service1Api service1 = mock(Service1Api.class);
Service2Api service2 = mock(Service2Api.class);
BusinessFlow businessFlow = new BusinessFlow("codeValue", service1, service2);

模拟数据对象或具有可重复或无状态行为的简单类(如JDK提供的)是不明智的

不鼓励现场注入,因为正是您遇到的问题


然而,如果您选择忽略这一公认的智慧,Spring确实为此提供了一个实用程序类:
org.springframework.test.util.ReflectionTestUtils

有了它,您可以在类中注入以下内容:

 BusinessFlow flow = new BusinessFlow();
 ReflectionTestUtils.setField(flow, "code", "testcode");
 ReflectionTestUtils.setField(flow, "service1", mockService);

当然,您可以直接使用Java反射API实现同样的功能,但这稍微方便一些。

使用apache commons反射方法初始化测试类中的字符串值,如下所示


writeField(类对象,“变量名”,“值”,true)

你为什么要模仿绳子?为什么不传递一个适合您需要的值呢。@litelite因为我想用不同的
code
值测试我的
BusinessFlow
。那么为什么不在每次创建/使用
BusinessFlow
时传递一个不同的值呢?你知道模拟和注入的区别吗?您想监视什么?@litelite原因与我无法传递服务值相同:在
BusinessFlow
Spring字段注入用于注入服务和
code
值。我的团队成员刚刚实现了这个想法。但我不喜欢这样:1。出于测试目的2,它需要更改源类。在一个类中引入了两种不同类型的DI:setter和field injection(请参阅我在文章中的更新)。@AndriyKryvtsun:以这种方式使用
@Autowired
是不受欢迎的;您应该考虑使用基于构造函数或基于setter的注入。然而,我没有发现自己在抱怨设计的改变;我确实提到过这对于重构来说是一个很好的练习。理论上我同意你的观点,但实际上先读一下我的评论,请读一下我之前的评论。评论为什么我不想进行重构第二,我的同事们总是在争论为什么我们应该引入更复杂的重构注入,因为我们可以用更少的详细字段注入达到同样的目标(@AndriyKryvtsun当然你可以通过字段注入达到同样的目标。好吧,几乎是同样的目标。这里有一个完美的例子说明为什么使用ctor注入更好:你可以轻松地测试你的类,甚至不必使用任何模拟库。但是,你总是可以使用Spring测试功能来提供假bean,而不是真实的bean一个。@AndriyKryvtsun您也可以使用反射将值注入到您的字段中。但在这种情况下,您依赖于类的实现。这不是一个好的做法。您应该测试行为,而不是实现。Spring测试bean方法是值得的选择,因为将我的单元测试转换为涉及Spring上下文的集成测试。