最佳做法是在方法中模拟/存根由构造函数创建的对象。

huangapple go评论62阅读模式
英文:

Best practice to mock/stub object created by constructor in a method

问题

I understand your request. Here's the translated part:

考虑一个带有参数化构造函数的POJO类:

public class Pojo {
    private String field1;
    private String field2;

    public Pojo(String field1, String field2) {
        this.field1 = field1;
        this.field2 = field2;
    }
}

现在我有一个需要进行单元测试的类,其中一个方法通过构造函数创建Pojo对象:

public class AnInjectMock {

    private ServiceClass serviceClass;

    public void runTransaction(Param1 param1, Param2 param2 ...) {
        Pojo pojo = new Pojo(param1.getField1(), param2.getField2());
        serviceClass.createTransaction(pojo, /*other fields*/);
        // ...
    }
}

我认为这不是一个罕见的实现场景。但是就单元测试而言,我试图找出一种只使用Mockito来存根构造函数对象的方法。我知道在Mockito 3.5之后有支持模拟构造函数,但是根据文档和其他在线教程,我找不到任何关于存根带有参数化构造函数的对象的信息。我可以接受对构造函数使用any()值。

英文:

(Currently I have junit and Mockito, PowerMock or EasyMock is not an option)
Considering a POJO class with parameterized constructor

public class Pojo{
    private String field1;
    private String field2;

    public Pojo(String field1, String field2){
        this.field1=field1, this.field2=field2;
    }
}

Now I have a class requires unit test and one of the method create Pojo object by the constructor

public class AnInjectMock{

    private ServiceClass serviceClass;
    //....
    public void runTransaction(Param1 param1, Param2 param2 ...){

        Pojo pojo = new Pojo(param1.getFiel1(), param2.getField2();
        
        serviceClass.createTransaction(pojo, /*other fields*/};
        .....
    }
}

I think this is not an uncommon implementation scenario. But as for unit test, I try to figure out a way to use Mockito only to stub the constructor object. I get it that after Mockito 3.5 there is support to mock constructor, however per the document and other online tutorial I couldn't find anything to stub the object with parameterized constructor. I am Ok with any() value for the constructor.

答案1

得分: 1

Here is the translated code portion:

如果我理解正确您需要模拟对象内的参数我认为您可以使用`when()`轻松模拟这些参数

@ExtendWith(MockitoExtension.class)
class AnInjectMockTest {

    @InjectMocks
    private AnInjectMock anInjectMock;

    @Mock
    private ServiceClass serviceClass;

    @Mock
    private Param1 param1;

    @Mock
    private Param2 param2;

    @Test
    public void myTest() {
        when(param1.getField1()).thenReturn(any());
        when(param2.getField2()).thenReturn(any());
        anInjectMock.createTransaction(pojo, /*other fields*/};
    }
}

顺便说一下您为什么需要模拟它也许更好的方法是从pojo创建一个对象然后模拟`createTransaction()`。

Pojo pojo = new Pojo("field1Value", "field2Value");
when(serviceClass.createTransaction(pojo, /*other fields*/)).thenReturn(any());

最后一点您可以使用WhiteBox来模拟构造函数

Pojo pojo = new Pojo("field1Value", "field2Value");
Whitebox.setInternalState(anInjectMock, "pojo", pojo);

但然后您需要添加WhiteBox的依赖

<!-- https://mvnrepository.com/artifact/org.powermock/powermock-reflect -->
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-reflect</artifactId>
    <version>1.6.1</version>
    <scope>test</scope>
</dependency>

I've provided the translated code portion as requested.

英文:

If I understood correctly you need to mock parameters inside the object. I think you can easily mock this parameters with when()

    @ExtendWith(MockitoExtension.class)
class AnInjectMockTest {
@InjectMocks
private AnInjectMock anInjectMock;
@Mock
private ServiceClass serviceClass;
@Mock
private Param1 param1;
@Mock
private Param2 param2;
@Test
public void myTest() {
when(param1.getField1()).thenReturn(any());
when(param2.getField2()).thenReturn(any());
anInjectMock.createTransaction(pojo, /*other fields*/};
}
}

By the way, why do you need to mock it? Maybe it's better to create an object from pojo and then mock createTransaction()

Pojo pojo = new Pojo(&quot;field1Value&quot;, &quot;field2Value&quot;);
when(serviceClass.createTransaction(pojo, /*other fields*/)).thenReturn(any());

And the last point. You can mock constructors with WhiteBox like:

Pojo pojo = new Pojo(&quot;field1Value&quot;, &quot;field2Value&quot;);
Whitebox.setInternalState(anInjectMock, &quot;pojo&quot;, pojo);

But then you need to add dependency for WhiteBox:

&lt;!-- https://mvnrepository.com/artifact/org.powermock/powermock-reflect --&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.powermock&lt;/groupId&gt;
&lt;artifactId&gt;powermock-reflect&lt;/artifactId&gt;
&lt;version&gt;1.6.1&lt;/version&gt;
&lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;

huangapple
  • 本文由 发表于 2023年5月13日 21:37:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/76243012.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定