Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/61.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
Methods 如何使用PowerMockito模拟私有方法的任何参数?_Methods_Junit_Mockito_Private_Powermock - Fatal编程技术网

Methods 如何使用PowerMockito模拟私有方法的任何参数?

Methods 如何使用PowerMockito模拟私有方法的任何参数?,methods,junit,mockito,private,powermock,Methods,Junit,Mockito,Private,Powermock,我使用的是Mockito 1.9.5、PowerMock 1.5.1、JUnit 4.11和Spring 3.1.4.RELEASE。我正试图编写一个JUnit测试,其中我想模拟一个不做任何事情的私有方法。私有方法签名是 public class MyService { … private void myMethod(byte[] data, UserFile userFile, User user) { 在我的JUnit测试中 @RunWith(SpringJUni

我使用的是Mockito 1.9.5、PowerMock 1.5.1、JUnit 4.11和Spring 3.1.4.RELEASE。我正试图编写一个JUnit测试,其中我想模拟一个不做任何事情的私有方法。私有方法签名是

public class MyService
{

    …
    private void myMethod(byte[] data, UserFile userFile, User user)
    {
在我的JUnit测试中

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "classpath:test-context.xml" })
@PrepareForTest(MyServiceImpl.class)
public class MyServiceIT 
{

    @Rule
    public PowerMockRule rule = new PowerMockRule();

    @Autowired
    private MyService m_mySvc;
    private MyService m_mySvcSpy;

    @Before
    public final void setup() throws Exception
    {
        m_mySvcSpy = PowerMockito.spy(m_mySvc);
        PowerMockito.doNothing().when(m_mySvcSpy, “myMethod”, Matchers.any(byte[].class), Matchers.any(UserFile.class), Matchers.any(User.class));
不幸的是,第二行出现了异常

testUploadFile(org.mainco.subco.user.service.MyServiceIT)  Time elapsed: 12.693 sec  <<< ERROR!

testUploadFile(org.mainco.subco.user.service.MyServiceIT)运行时间:12.693秒我猜您的测试是用
SpringJUnit4ClassRunner
注释的。在这种情况下,您必须使用:

此外,您正在使用powermock存根
MyService
方法。因此,必须使用以下内容注释测试类:


完整代码:

@PrepareForTest(MyServiceImpl.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class MyServiceTest {
    @Rule
    public PowerMockRule rule = new PowerMockRule();

    @Autowired
    private MyService service;
    private MyService spy;

    @Before
    public final void setup() throws Exception {
        spy = PowerMockito.spy(service);
        PowerMockito.doNothing().when(spy,
                "myMethod",
                Matchers.any(byte[].class),
                Matchers.any(UserFile.class),
                Matchers.any(User.class));
    }

    ...
}

你可以看到

你的问题的前提似乎暗示你违反了规则;如果需要测试私有方法,并且需要将其注入到它中,那么您应该考虑将其移至不同的服务。

我建议您执行以下操作:

public class MyService implements IService { // I know it's not a strong convention in
                                             // the Java world, but I'm primarily a C#
                                             // guy, so I tend to give any interface a
                                             // name that starts with captital "I"

    public MyService(IDependencyOne dep1, IDependencyTwo dep2) {
        // ...
    }

    public Stuff getTheStuffThatAnIServiceGets() {
        // your previously private method was used here before
        // Now, it's instead a method defined on the IDependencyTwo interface,
        // so you have it available as _dep2.myMethod(...)
    }
}

public class OtherService implements IDependencyTwo {
    public void myMethod(/* possibly some arguments... */) {
        // ...
    }
}

通过这种分离,您可以在测试MyService时注入模拟先前私有方法行为的内容(仅模拟
IDependencyTwo
),类似地,您可以通过模拟和注入
IDependencyTwo

的依赖项来模拟需要注入到以前私有方法中的任何内容。我还没有对它进行测试,但我相信,私有方法找不到的原因是,它不存在于Spring为
MyService
接口提供的对象中。这个对象是一个代理,一个生成的类的实例,它不扩展MyServiceImpl
;因此,其中没有
私有myMethod(…)


为了避免这个问题,测试不应该使用弹簧。相反,直接在
setup()
方法中实例化
MyServiceImpl
。如果测试需要将其他依赖项注入
m_mySvc
,则为这些依赖项创建mock,并让PowerMock注入它们。

因为您看到了此异常:

org.powermock.reflect.exceptions.MethodNotFoundException:在类中找不到名为“myMethod”且参数类型为:[null,null,null]的方法

你能试着使用mockito的matcher吗(可能还有一些类型转换)

换句话说,您使用

PowerMockito.doNothing().when(m_myvcspy,“myMethod”,Matchers.isNull(byte[].class),Matchers.isNull(UserFile.class),Matchers.isNull(User.class))

顺便说一句,您可以使用
Matchers.isNull
,这样您就可以简单地使用
isNull
而不是
Matchers.isNull

我继续使用了“抑制”


在我的例子中,我希望私有方法“返回”一些东西,所以我就是这么做的

        MyTestClass spyInstance = spy(MyTestClass.getNewInstance());
        MyGenericClass obj = mock(MyGenericClass.class);

           doReturn(obj).when(spyInstance,method(MyTestClass.class,"privateMethod",
            String.class,HashMap.class,Class.class)).
            withArguments("624",null,MyGenericClass.class);`
我的私人方法是

private <T> T privateMethod(String str,HashMap<String,String> map,Class<T> c)
private T privateMethod(字符串str,HashMap映射,c类)

我更新了代码以反映您的建议。然而,我仍然得到与上面相同的异常,发生在您的第一个“doNothing”调用中(spy=后面的行)。不确定这是否重要,但“MyService.class”是一个接口。实现类“MyServiceImpl.class”实际上包含私有方法。我删除了第二个
不做任何事情,这是一个错误。知道
MyService
是一个接口非常重要。您必须使用
@PrepareForTest(myserviceinpl.class)
。您好,我更新了我的答案以反映您的代码,但运行它仍然会产生相同的异常,“org.powermock.reflect.exceptions.MethodNotFoundException:未找到名为'myMethod'且参数类型为的方法“doNothing必须使用MyServiceImpl调用。嗨,不幸的是,现在不能将私有方法移出实现类。既然如此,我该如何解决我的问题呢?我传递给方法的参数不是空的。嗯,你能发布单元测试代码吗?异常看起来您在某个单元测试中传递了null。代码非常出色。它甚至没有通过@Before(setup)方法,死在我调用“Powermock.doNothing()…”的行上。我有一些POC编码,显示
字节[]数据
参数可以正确模拟,这表明原因可能与您的
org.mainco.subco.user.service.UserFileService
有关。你能解释一下
UserFile
User
有什么吗?你可以尝试的另一件事(如果你没有)是调试你的单元测试并进入有问题的代码。我不明白为什么PowerMockito.doNothing()会在(m_myvcspy,“myMethod”,null,null)时出现;电话线在那里。它应该在做什么?
suppress(method(MyServiceImpl.class,  “myMethod”));
        MyTestClass spyInstance = spy(MyTestClass.getNewInstance());
        MyGenericClass obj = mock(MyGenericClass.class);

           doReturn(obj).when(spyInstance,method(MyTestClass.class,"privateMethod",
            String.class,HashMap.class,Class.class)).
            withArguments("624",null,MyGenericClass.class);`
private <T> T privateMethod(String str,HashMap<String,String> map,Class<T> c)