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

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

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

问题

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

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

  1. public class Pojo {
  2. private String field1;
  3. private String field2;
  4. public Pojo(String field1, String field2) {
  5. this.field1 = field1;
  6. this.field2 = field2;
  7. }
  8. }

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

  1. public class AnInjectMock {
  2. private ServiceClass serviceClass;
  3. public void runTransaction(Param1 param1, Param2 param2 ...) {
  4. Pojo pojo = new Pojo(param1.getField1(), param2.getField2());
  5. serviceClass.createTransaction(pojo, /*other fields*/);
  6. // ...
  7. }
  8. }

我认为这不是一个罕见的实现场景。但是就单元测试而言,我试图找出一种只使用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

  1. public class Pojo{
  2. private String field1;
  3. private String field2;
  4. public Pojo(String field1, String field2){
  5. this.field1=field1, this.field2=field2;
  6. }
  7. }

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

  1. public class AnInjectMock{
  2. private ServiceClass serviceClass;
  3. //....
  4. public void runTransaction(Param1 param1, Param2 param2 ...){
  5. Pojo pojo = new Pojo(param1.getFiel1(), param2.getField2();
  6. serviceClass.createTransaction(pojo, /*other fields*/};
  7. .....
  8. }
  9. }

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:

  1. 如果我理解正确您需要模拟对象内的参数我认为您可以使用`when()`轻松模拟这些参数
  2. @ExtendWith(MockitoExtension.class)
  3. class AnInjectMockTest {
  4. @InjectMocks
  5. private AnInjectMock anInjectMock;
  6. @Mock
  7. private ServiceClass serviceClass;
  8. @Mock
  9. private Param1 param1;
  10. @Mock
  11. private Param2 param2;
  12. @Test
  13. public void myTest() {
  14. when(param1.getField1()).thenReturn(any());
  15. when(param2.getField2()).thenReturn(any());
  16. anInjectMock.createTransaction(pojo, /*other fields*/};
  17. }
  18. }
  19. 顺便说一下您为什么需要模拟它也许更好的方法是从pojo创建一个对象然后模拟`createTransaction()`
  20. Pojo pojo = new Pojo("field1Value", "field2Value");
  21. when(serviceClass.createTransaction(pojo, /*other fields*/)).thenReturn(any());
  22. 最后一点您可以使用WhiteBox来模拟构造函数
  23. Pojo pojo = new Pojo("field1Value", "field2Value");
  24. Whitebox.setInternalState(anInjectMock, "pojo", pojo);
  25. 但然后您需要添加WhiteBox的依赖
  26. <!-- https://mvnrepository.com/artifact/org.powermock/powermock-reflect -->
  27. <dependency>
  28. <groupId>org.powermock</groupId>
  29. <artifactId>powermock-reflect</artifactId>
  30. <version>1.6.1</version>
  31. <scope>test</scope>
  32. </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()

  1. @ExtendWith(MockitoExtension.class)
  2. class AnInjectMockTest {
  3. @InjectMocks
  4. private AnInjectMock anInjectMock;
  5. @Mock
  6. private ServiceClass serviceClass;
  7. @Mock
  8. private Param1 param1;
  9. @Mock
  10. private Param2 param2;
  11. @Test
  12. public void myTest() {
  13. when(param1.getField1()).thenReturn(any());
  14. when(param2.getField2()).thenReturn(any());
  15. anInjectMock.createTransaction(pojo, /*other fields*/};
  16. }
  17. }

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

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

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

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

But then you need to add dependency for WhiteBox:

  1. &lt;!-- https://mvnrepository.com/artifact/org.powermock/powermock-reflect --&gt;
  2. &lt;dependency&gt;
  3. &lt;groupId&gt;org.powermock&lt;/groupId&gt;
  4. &lt;artifactId&gt;powermock-reflect&lt;/artifactId&gt;
  5. &lt;version&gt;1.6.1&lt;/version&gt;
  6. &lt;scope&gt;test&lt;/scope&gt;
  7. &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:

确定