是否可以在Activity类中测试方法?

New*_*per 6 junit android unit-testing android-testing

每个人都建议遵循MVP或MVVM模式以保持代码的可读性和可测试性。现在我有疑问。现在,我正在学习单元测试,并以一种正式的方式编写代码。不使用任何模式。现在我的问题是,我可以像下面那样测试我的代码吗?

我的主要活动:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main); 
    }

    public boolean testMethod(int value){
       return value== 5?true:false;
    }
}
Run Code Online (Sandbox Code Playgroud)

我的单元测试课:

@RunWith(MockitoJUnitRunner.class)
public class ExampleUnitTest {
 MainActivity mainActivity = new MainActivity();
@Test
    public void testMethod(){
        boolean result = mainActivity.testMethod(5);
        assertEquals(true,result);
    }
}
Run Code Online (Sandbox Code Playgroud)

在运行测试时,我没有收到任何错误或问题。那么这是正确的测试方法吗?还是如果我遵循这种方法会发生什么?我也开始将代码迁移到MVP模式,但是我想清除我的疑问。请让我知道为什么我不遵循单元测试的正式编码的原因。

Mai*_*aik 6

您的简单示例之所以有效,是因为被测试的代码实际上并不依赖于Activity类或任何UI状态。尝试针对实际上取决于UI状态的代码编写测试,例如

public boolean verifyInput() {
    EditText edit = findViewById(R.id.edit1);
    return edit.getText().toString().startsWith("0");
}
Run Code Online (Sandbox Code Playgroud)

如果继续走这条路,您会发现以下事情发生:

  • 您的Activity课程将会越来越大(上帝对象反模式)。
  • 实际依赖于UI状态的代码(您的示例并不如此)无法使用简单的单元测试来编写,因此需要Android仪表测试。即测试将不再能够在您的主机上执行,而必须在设备上执行,并且需要进行设置并将其Activity置于正确的状态。
  • 由于处理UI动作和状态需要进行所有繁重的工作,因此仪表测试通常会比较慢,并且可能会很不稳定。您将在测试运行中收到假阴性。
  • 测试方法将变得更加复杂,因为它们必须使UI进入正确的状态以测试逻辑。

现在,有一个简单的解决方案。将核心逻辑与UI逻辑分开。使处理UI的代码尽可能简单,并将(复杂的)核心逻辑移到单独的类中。突然,您有了一个带有方法的第二类,这将使您更容易推理和编写测试。第二类也将匹配您的应用程序用户将能够执行的操作。

一段时间后,您将也想拆分第二类,因为您会注意到某些方法子集与另一方法子集无关。因此,您将保持模块化和精心设计,以使开发人员更容易理解和使用代码。这是MVP,MVVM等模式变得方便的时候。

请注意,我不建议您立即使用MVVM之类的模式。如果您刚刚开始学习编程,软件开发或Android,那么完全可以做自己的事。您将通过体验这些“痛点”来学习,这是我们很多人已经遇到的,那时您将开始寻找改进之处,以及为什么其他人建议使用特定的模式或最佳实践。

另外,请查看低耦合和高内聚力的含义以及为什么它对您作为开发人员很重要。