Java Mockito – 验证调用具有引用类型参数的方法

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

Java Mockito - verify method called with reference type parameter

问题

你可以使用Mockitoeq()方法来处理类类型参数的匹配。在你的示例中,你可以像这样使用它:

when(MyUtils.getUserFromOtherPlace(eq(UserType.ADMIN))).thenReturn(adminUser);

这应该能够解决你的问题。这里的eq()方法用于匹配参数,确保参数与预期的一致。希望这对你有所帮助!

英文:

I am new to using Mockito while I am verifying certain method should be called with a specific parameter, while all the value type parameter (int, String, enum etc) could be verified, but reference/class type parameter seems not, here is an example

// my actual class
public class MyActualClass {
   public void processRequest() {
       User curUser = MyUtils.getUserFromOtherPlace(UserType.ADMIN);
       processAnotherRequest(1, "address", curUser);
   }
   public void processAnotherRequest(int userId, String address, User user) { ... }
}
public static class MyUtils{
   public static getUserFromOtherPlace(UserType userType) {
       User newUser = new User();
       if (userType == UserType.ADMIN) {
          newUser.setAccess(1);
       }
       //...
       return newUser
   }
}

// my test class
public class MyActualClassTest{
   @Mock
   private MyActualClass myActualClass;

   @Test
   public void testIfMethodBeingCalledCorrectly() {
      User adminUser = new User();
      adminUser.setAccess(1);
      doCallRealMethod().when(myActualClass).processRequest();
      myActualClass.processRequest();
      verify(myActualClass).processAnotherRequest(1, "address", adminUser);
   }
}

I know it might because the adminUser set in my test method was not the same reference object that'd be generated through my actual method getUserFromOtherPlace -> MyUtils.getUserFromOtherPlace, I also tried to mock the return object with my static method like

// tried 1
when(MyUtils.getUserFromOtherPlace(UserType.ADMIN).thenReturn(adminUser);  // this throws error like "You cannot use argument matchers outside of verification or stubbing", and suggest using eq()
// tried 2
when(MyUtils.getUserFromOtherPlace(eq(UserType.ADMIN)).thenReturn(adminUser); //this throws NullPointer exception in getUserFromOtherPlace when check the input enum parameter "userType"

So how could I pass the reference object into my entry method and mock it as return value of my internal method here? BTW, if my method only contains value type parameter, it will work...

答案1

得分: 1

为了模拟静态方法,您需要:

@RunWith(PowerMockRunner.class)
@PrepareForTest({ MyUtils.class })

// 在这里放入您的测试类

@Before
public void setup() {
    PowerMockito.mockStatic(MyUtils.class);
    when(MyUtils.getUserFromOtherPlace(UserType.ADMIN)).thenReturn(adminUser);
}

但是,如果有其他选项,我总是更喜欢不模拟静态类,也许您可以尝试使用参数捕获器:

// 测试类

@Captor
private ArgumentCaptor<User> captor;

// 您的测试方法
@Test
public void testIfMethodBeingCalledCorrectly() {
    doCallRealMethod().when(myActualClass).processRequest();
    myActualClass.processRequest();
    verify(myActualClass, times(1)).processAnotherRequest(1, "address", 
        captor.capture());
    Assert.assertEquals(1, captor.getValue().getAccess());
}
英文:

So in order to mock you static method you will need to:

@RunWith(PowerMockRunner.class)
@PrepareForTest({ MyUtils.class })

//your test class here

@Before
public void setup() {
    PowerMockito.mockStatic(MyUtils.class);
	when(MyUtils.getUserFromOtherPlace(UserType.ADMIN).thenReturn(adminUser);
}

But I always prefer not to mock static classes if there is another option so maybe you could try a argument captor:

//test class

@Captor
private ArgumentCaptor&lt;User&gt; captor;

//your test
@Test
public void testIfMethodBeingCalledCorrectly() {
    doCallRealMethod().when(myActualClass).processRequest();
    myActualClass.processRequest();
    verify(myActualClass, times(1)).processAnotherRequest(1, &quot;address&quot;, 
        captor.capture());
    Assert.assertEquals(1, captor.getValue().getAccess());
}

答案2

得分: 0

首先,除非您不使用powermock,否则无法对静态方法进行模拟。相反,您可以将User对象作为参数传递给processRequest。

public void processRequest(User curUser) {
    processAnotherRequest(1, "address", curUser);
}

public void processAnotherRequest(int userId, String address, User user) {
    //...
}

然后,您可以在测试代码中使用对象引用。

User adminUser = MyUtils.getUserFromOtherPlace(UserType.ADMIN);
adminUser.setAccess(1);
doCallRealMethod().when(myActualClass).processRequest(adminUser);
myActualClass.processRequest(adminUser);
verify(myActualClass).processAnotherRequest(1, "address", adminUser);
英文:

First of all, you cannot mock a static method unless you don't use powermock. Instead, you can pass User object as a parameter to processRequest.

public void processRequest(User curUser) {
    processAnotherRequest(1, &quot;address&quot;, curUser);
}

public void processAnotherRequest(int userId, String address, User user) {
    //...
}

Then, you can use the object reference in the test code.

User adminUser = MyUtils.getUserFromOtherPlace(UserType.ADMIN);
adminUser.setAccess(1);
doCallRealMethod().when(myActualClass).processRequest(adminUser);
myActualClass.processRequest(adminUser);
verify(myActualClass).processAnotherRequest(1, &quot;address&quot;, adminUser);

huangapple
  • 本文由 发表于 2020年7月30日 08:02:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/63164241.html
匿名

发表评论

匿名网友

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

确定