Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.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
用Mockito进行Android单元测试_Android_Unit Testing_Junit_Mockito_Android Mvvm - Fatal编程技术网

用Mockito进行Android单元测试

用Mockito进行Android单元测试,android,unit-testing,junit,mockito,android-mvvm,Android,Unit Testing,Junit,Mockito,Android Mvvm,我有一个ViewModel,其中有一个方法具有以下代码行: billDate.set(!TextUtils.isEmpty(SampleApp.getInstance().getAccountManager().getDueDate()) ? String.format(SampleApp.getInstance().getApplicationContext().getString(R.string.due), SampleApp

我有一个ViewModel,其中有一个方法具有以下代码行:

billDate.set(!TextUtils.isEmpty(SampleApp.getInstance().getAccountManager().getDueDate()) ?
            String.format(SampleApp.getInstance().getApplicationContext().getString(R.string.due),
                    SampleApp.getInstance().getAccountManager().getBillingDueDate()) :
            SampleApp.getInstance().getApplicationContext().getString(R.string.missing_due_date));
我有一个使用Mockito测试ViewModel中不同方法的测试类。但它在这一行中失败,出现了
NullPointerException

String.format(SampleApp.getInstance().getApplicationContext().getString(R.string.due),
以下是日志:

java.lang.NullPointerException
at java.util.regex.Matcher.getTextLength(Matcher.java:1283)
at java.util.regex.Matcher.reset(Matcher.java:309)
at java.util.regex.Matcher.<init>(Matcher.java:229)
at java.util.regex.Pattern.matcher(Pattern.java:1093)
at java.util.Formatter.parse(Formatter.java:2547)
at java.util.Formatter.format(Formatter.java:2501)
at java.util.Formatter.format(Formatter.java:2455)
at java.lang.String.format(String.java:2940)
java.lang.NullPointerException
位于java.util.regex.Matcher.getTextLength(Matcher.java:1283)
位于java.util.regex.Matcher.reset(Matcher.java:309)
位于java.util.regex.Matcher.(Matcher.java:229)
位于java.util.regex.Pattern.matcher(Pattern.java:1093)
位于java.util.Formatter.parse(Formatter.java:2547)
位于java.util.Formatter.format(Formatter.java:2501)
位于java.util.Formatter.format(Formatter.java:2455)
位于java.lang.String.format(String.java:2940)
在运行测试用例时,我看到日志显示了一些与
模式相关的错误

有人能建议如何测试
String.format()
方法吗

首先,您不应该将android视图包导入到ViewModel中。因此,请跳过在ViewModels内部使用
TextUtils

对于
getApplicationContext().getString()
,请为此创建一个接口。比如:

interface StringProvider {
    String getString(int resource);
}
然后在ViewModel构造函数中传递该接口,并使用该接口获取所需的字符串

初始化ViewModel时,可以传递
StringProvider
的具体实现,如下所示:

class StringProviderImpl implements StringProvider {
     String getString(int resource) {
        return SampleApp.getInstance().getApplicationContext().getString(resource);
     }
}

这样,对于您的单元测试,您可以只模拟
StringProvider
,而不必担心如何处理ViewModel和相关测试代码中的上下文。

您不需要测试
String.format
方法。这不是您的代码,您的目标应该是测试您自己的代码。但是您的代码正在使用该方法,因此您需要测试您的代码。据我所知,这是您试图验证或模拟的部分:

String.format(SampleApp.getInstance().getApplicationContext().getString(R.string.due), SampleApp.getInstance().getAccountManager().getBillingDueDate()) 
它多次调用SampleApp以获取实例。由于对SampleApp.getInstance的调用是静态方法调用,因此您将无法模拟它们。发布的代码不足,无法知道SampleApp是什么或SampleApp.getInstance()返回什么,也无法知道该实例上的任何后续调用是否返回null,但其中一个是。所以我认为要解决这个问题,您需要查看getInstance方法返回的内容。如果您不能接触该代码,并且希望只修改您的测试类,那么由于静态方法的原因,您可能无法使用mockito对其进行测试

但是,否则,您需要为测试构建一种方法,这样对
SampleApp.getInstance
的调用将返回一个模拟对象作为实例,而不是我认为它现在返回的任何真实实例。然后,您可以模拟后续的方法,如getApplicationContext和getString,使它们返回固定的响应,以便
string.format
调用不会在空输入时失败


需要注意的是,如果最终使静态getInstance方法返回一个mock,但是确保在测试完成时进行了适当的清理,以将其设置回最初返回的状态,这样就不会无意中修改可能导致另一个不相关的单元测试失败的内容。如果您在单元测试中更改静态方法返回的内容,这始终是一个风险,因为您正在为所有测试有效地更改它。

考虑到在使用了
AccountManager
之后测试失败,您应该已经将
SampleApp
设置为模拟或伪

SampleApp app = SampleApp.getInstance()
AccountManager am = app.getAccountManager();
Context context = app.getApplicationContext();
billDate.set(!TextUtils.isEmpty(am.getDueDate()) ?
    String.format(context.getString(R.string.due), am.getBillingDueDate()) :
    context.getString(R.string.missing_due_date);
现在,如果您直接使用
app.getApplicationContext()
,则只需确保模拟您随
app.getApplicationContext()提供的
上下文或
SampleApp
本身

doReturn(dueFormatString).when(context).getString(R.string.due);
doReturn(dueMissingString).when(context).getString(R.string.missing_due_date);
但一般来说,您应该将
上下文
抽象掉。不使用它将简化您的代码,从而大大简化您的测试

还考虑使用<代码>上下文.GETString()<代码>,而不是<代码> Stry.FrimATA()/<代码>,用于格式化从资源加载的字符串。将格式参数作为参数添加到调用中非常简单

context.getString(R.string.due, am.getBillingDueDate())

你能发布完整的stacktrace吗?@Giorgioantonili我已经粘贴了日志你能添加相关的测试用例吗?getString的默认实现返回null,你可以模拟它或使用包装器接口,如StringProvider。请将测试用例与模拟类@Lavanya一起发布在本例中,是ViewModel类StringProviderImpl吗?