Layout for creating an object inside a method

Description of the problem

I am trying to make fun of creating an object inside a method. I have LoginFragmentone that creates LoginPresenterImplinside the method onCreateas shown below:

public class LoginFragment extends BaseFragment {
    private LoginPresenter mPresenter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mPresenter = new LoginPresenterImpl(this); <<-- Should be mocked
    }

}

I have some problems with the union RobolectricGradleTestRunner, and PowerMockRunnerin a single test, but after reading this publication, I found a way to do it, so my test is as follows:

BaseRobolectricTest.java

@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class, sdk = 21)
@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"})
public abstract class BaseRobolectricTest {

}

Test.java

@PrepareForTest({LoginPresenterImpl.class})
public class Test extends BaseRobolectricTest  {

    private LoginPresenterImpl mPresenterMock;

    @Rule
    public PowerMockRule rule = new PowerMockRule();

    @Before
    public void setup() {
        mockStatic(LoginPresenterImpl.class);

        mPresenterMock = PowerMockito.mock(LoginPresenterImpl.class);
    }

    @Test
    public void testing() throws Exception {
        when(mPresenterMock.loadUsername(any(Context.class))).thenReturn(VALID_USERNAME);
        when(mPresenterMock.loadPassword(any(Context.class))).thenReturn(VALID_PASSWORD);
        when(mPresenterMock.canAutologin(VALID_USERNAME, VALID_PASSWORD)).thenReturn(true);

        whenNew(LoginPresenterImpl.class).withAnyArguments().thenReturn(mPresenterMock);

        FragmentTestUtil.startFragment(createLoginFragment());
    }

    private LoginFragment createLoginFragment() {
        LoginFragment loginFragment = LoginFragment.newInstance();
        return loginFragment;
    }
}
+4
source share
4 answers

This is just bad code and the opposite of the Dependency Injection pattern.

, Dagger, , .

mocks :

@Module
public class TestDataModule extends DataModule {

    public TestDataModule(Application application) {
        super(application);
    }

    @Override
    public DatabaseManager provideDatabaseManager(DatabaseUtil databaseUtil) {
        return mock(DatabaseManager.class);
    }
}

.

SOLID .

+4

, , ...

public class LoginFragment extends BaseFragment {
    private LoginPresenter mPresenter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mPresenter = getLoginPresenter();
    }

    protected LoginPresenter getLoginPresenter() {
        return new LoginPresenterImpl(this);
    }
}

Test.java

private LoginFragment createLoginFragment() {
    LoginFragment loginFragment = LoginFragmentTest.newInstance();
    return loginFragment;
}

private static class LoginFragmentTest extends LoginFragment {
    @Override
    protected LoginPresenter getLoginPresenter() {
        return mPresenterMock;
    }
}
+1

-, , , .

factory, LoginPresenter. factory LoginFragment. factory onCreate. factory , LoginPresenter. POJO, .

public class LoginFragment extends BaseFragment {
    private LoginPresenter mPresenter;
    private final LoginPresenterFactory presenterFactory;

    public LoginFragment(LoginPresenterFactory presenterFactory) {
        this.presenterFactory = presenterFactory;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mPresenter = presenterFactory.create();
    }
}
+1

, . - , .

, , .

public class ReflectionUtility
{
  public static void setValue(Object obj, String fieldName, Object value)
  {
    try
    {
      final Field field = obj.getClass().getDeclaredField(fieldName);
      field.setAccessible(true);
      field.set(obj, value);
    }
    catch (IllegalAccessException e)
    {
      throw new RuntimeException(e);
    }
    catch (NoSuchFieldException e)
    {
      throw new RuntimeException(e);
    }
  }
}

then in your test,



private LoginFragment createLoginFragment()
{
    LoginFragment loginFragment = LoginFragment.newInstance();
    ReflectionUtility.setValue(loginFragment, "mPresenter", mPresenterMock);
    return loginFragment;
}
+1

Source: https://habr.com/ru/post/1653901/


All Articles