我已经切换到MVP架构并尝试测试它。我对如何构建我的Presenter有一些疑问。
public class Presenter
{
public void onResume()
{
doA();
doB();
doC();
}
protected void doA() {};
protected void doB() {};
protected void doC() {};
}
public class MyScreen implements MyScreenView
{
private Presenter presenter;
public MyScreen()
{
presenter = new Presenter(this);
}
public OnResume()
{
presenter.OnResume();
}
}
在上面的代码中,当视图恢复时,视图只调用演示者OnResume()。演示者在内部调用3个方法,doA(),doB()和doC()来完成它必须做的任何事情。
或者,我可以直接在视图中调用doA(),doB()和doC():
public class Presenter
{
public void doA() {};
public void doB() {};
public void doC() {};
}
public class MyScreen implements MyScreenView
{
private Presenter presenter;
public MyScreen()
{
presenter = new Presenter(this);
}
public OnResume()
{
presenter.doA();
presenter.doB();
presenter.doC();
}
}
我的问题是,我更容易测试第二个解决方案,因为演示者被彻底分解为3个单独的公共单独责任方法,我可以单独编写doA,doB和doC的测试而不是单个测试解决方案1的presenter.onResume()方法。
在第一个解决方案中,我必须为onResume()编写测试,它负责调用这3个方法。这意味着它更难以测试,因为与调用其他私有函数的函数相比,它更容易测试个体责任的较小函数。然而,第二种解决方案在我看来并不像一个好的MVP,因为它似乎知道主持人正在做什么,并且只是不让主持人在第一个解决方案的onResume()方法中做它应该做的事情。
答案 0 :(得分:1)
如果将MyScreen类更改为
public class MyScreen implements MyScreenView
{
private presenter;
public MyScreen()
{
presenter = new Presenter();
}
public MyScreen(Presenter p)
{
presenter = p;
}
public OnResume()
{
presenter.OnResume();
}
}
然后你有一个生产构造函数,它创建一个新的Presenter和一个方便的构造函数进行测试,这样你就可以用Mock presenter实例化它。我更喜欢Mockito(来自记忆的代码......)
Presenter mockP = Mock(Presenter.class);
MyScreen target = new MyScreen(mockP);
target.OnResume();
verify(mockP).doA();
verify(mockP).doB();
verify(mockP).doC();
在这里,您可以使用Mock Presenter创建一个新的自选画面。当您在各种方法上调用verify时,如果从未在模拟上调用该方法,则测试将失败。因此,如果您在MyScreen类上调用OnResume,那么您实际上正在编写一个断言的测试,其效果是在其演示者字段上调用doA,doB和doC。
您可以在验证方法被调用时指定您期望的参数。并且您可以存根mockP的方法,以便它在特定场景中返回已知结果。
顺便提及
public OnResume()
{
presenter.OnResume();
}
是恕我直言,您可以选择两个选项,因为这样您就可以更改presenter.OnResume()
方法的功能,而无需更改MyScreen类。
答案 1 :(得分:1)
首先在My Screen类
中进行演示者注射public class MyScreen implements MyScreenView
{
private presenter;
public MyScreen()
{
presenter = this(new Presenter());
}
public MyScreen(Presenter p)
{
presenter = p;
}
public OnResume()
{
presenter.OnResume();
}
}
现在,您可以通过注入模拟来测试MyScreen的行为。
Presenter mockP = Mock(Presenter.class);
MyScreen target = new MyScreen(mockP);
target.OnResume();
verify(mockP).doA();
verify(mockP).doB();
verify(mockP).doC();
在完全独立的测试中,您可以测试演示者:
Presenter presenter = new Presenter();
presenter.onResume();
assertEquals("some State that should be true after calling on resume", presenter.getSomeMagicState());
不要通过检查演示者的状态来测试onResume调用doA,doB和doC,测试方法的行为。
如果doX确实变得复杂,请将其解压缩到一个单独的类中,对其进行测试,将其注入演示者并测试它是否被调用。