2017-04-05 84 views
1

我想在Android Studio中爲此類編寫單元測試,但由於使用Firebase,我在創建測試以覆蓋usersignin()和getSignedinUserprofile()方面存在問題。有人對這個有經驗麼?在Android Studio中使用Firebase進行JUnit測試

public class LoginActivity extends AppCompatActivity implements View.OnClickListener{ 


private Button buttonSignIn; 
private EditText editTextEmail; 
private EditText editTextPassword; 
private TextView textViewSignUp; 

private ProgressDialog mProgressDialog; 
private FirebaseAuth mfireBaseAuth; 
private DatabaseReference mDatabase; 
private String userID; 
private FirebaseUser firebaseUser; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_login); 
    FirebaseApp.initializeApp(this); 

    mfireBaseAuth = FirebaseAuth.getInstance(); 
    mDatabase = FirebaseDatabase.getInstance().getReference(); 
    mProgressDialog = new ProgressDialog(this); 
    editTextEmail = (EditText) findViewById(R.id.editTextEmail); 
    editTextPassword = (EditText) findViewById(R.id.editTextPassword); 
    buttonSignIn = (Button) findViewById(R.id.buttonSignIn); 
    textViewSignUp = (TextView) findViewById(R.id.textViewSignUp); 

    buttonSignIn.setOnClickListener(this); 
    textViewSignUp.setOnClickListener(this); 

} 

@Override 
public void onClick(View v) { 
    if(v == buttonSignIn){ 
     usersignin();} 
    if(v==textViewSignUp){ 
     startActivity(new Intent(this, RegisterActivity.class));} 


} 

public void usersignin() { 

    String email = editTextEmail.getText().toString().trim(); 
    String password = editTextPassword.getText().toString().trim(); 

    if(TextUtils.isEmpty(email)){ 
     Toast.makeText(this, "Please enter Email", Toast.LENGTH_SHORT).show(); 
     return; 
    } 

    if(TextUtils.isEmpty(password)){ 
     Toast.makeText(this, "Please enter password", Toast.LENGTH_SHORT).show(); 
     return; 
    } 

    mProgressDialog.setMessage("Logging in. Please wait..."); 
    mProgressDialog.show(); 
    mfireBaseAuth.signInWithEmailAndPassword(email, password).addOnCompleteListener(this, new OnCompleteListener<AuthResult>() { 
     @Override 
     public void onComplete(@NonNull Task<AuthResult> task) { 
      mProgressDialog.dismiss(); 
      if(task.isSuccessful()){ 
       getSignedInUserProfile(); 
      } 
     } 
    }); 
} 

public void getSignedInUserProfile() { 

    DatabaseReference reference = mDatabase;//.child("eduback-2feef"); 
    firebaseUser = FirebaseAuth.getInstance().getCurrentUser(); 
    userID = firebaseUser.getUid(); 
    reference.child("Users").child(userID).child("User info").addListenerForSingleValueEvent(new ValueEventListener() { 
     @Override 
     public void onDataChange(DataSnapshot dataSnapshot) { 
      User user = dataSnapshot.getValue(User.class); 
      if(user != null) { 
       // Save if the user is student or prof in shared prefs. 
       PreferenceHelper helper = new PreferenceHelper(getBaseContext()); 
       helper.setIsStudent(user.isStudent); 
       checkStudentOrProfessor(user); 
      } 

     } 

     @Override 
     public void onCancelled(DatabaseError databaseError) { 
      // Ups vis error 
     } 
    }); 
} 

public void checkStudentOrProfessor(User user) { 

    Intent i; 
    if (user.isStudent) { 
     i = new Intent(this, MainActivityStudent.class); 
    } else { 
     i = new Intent(this, MainActivityProfessor.class); 
    } 
    startActivity(i); 
} 
+1

請解耦數據庫代碼分離的類型。表示層不應該知道它使用的是Firebase。用'authUser()'方法寫一個接口,使用依賴注入,這樣你就可以爲活動注入一個模擬接口。 – slowy

回答

4

您可以使用Mockito和PowerMockito來模擬Firebase依賴關係。爲了模擬靜態函數(如FirebaseDatabase.getInstance()),必須使用PowerMockRunner來運行測試,但它可以稍後委託給不同的運行器。

package com.test.firebasetest; 

import com.google.firebase.database.DataSnapshot; 
import com.google.firebase.database.DatabaseReference; 
import com.google.firebase.database.FirebaseDatabase; 
import com.google.firebase.database.ValueEventListener; 

import org.junit.Before; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.mockito.Mockito; 
import org.mockito.invocation.InvocationOnMock; 
import org.mockito.stubbing.Answer; 
import org.powermock.api.mockito.PowerMockito; 
import org.powermock.core.classloader.annotations.PrepareForTest; 
import org.powermock.modules.junit4.PowerMockRunner; 

import static org.mockito.Matchers.any; 
import static org.mockito.Matchers.anyString; 
import static org.mockito.Mockito.doAnswer; 
import static org.mockito.Mockito.when; 

@RunWith(PowerMockRunner.class) 
@PowerMockRunnerDelegate(JUnit4.class) 
@PrepareForTest({ FirebaseDatabase.class}) 
public class LoginActivityTest { 

    private DatabaseReference mockedDatabaseReference; 

    @Before 
    public void before() { 
    mockedDatabaseReference = Mockito.mock(DatabaseReference.class); 

    FirebaseDatabase mockedFirebaseDatabase = Mockito.mock(FirebaseDatabase.class); 
    when(mockedFirebaseDatabase.getReference()).thenReturn(mockedDatabaseReference); 

    PowerMockito.mockStatic(FirebaseDatabase.class); 
    when(FirebaseDatabase.getInstance()).thenReturn(mockedFirebaseDatabase); 
    } 

    @Test 
    public void getSignedInUserProfileTest() { 
    when(mockedDatabaseReference.child(anyString())).thenReturn(mockedDatabaseReference); 

    doAnswer(new Answer<Void>() { 
     @Override 
     public Void answer(InvocationOnMock invocation) throws Throwable { 
     ValueEventListener valueEventListener = (ValueEventListener) invocation.getArguments()[0]; 

     DataSnapshot mockedDataSnapshot = Mockito.mock(DataSnapshot.class); 
     //when(mockedDataSnapshot.getValue(User.class)).thenReturn(testOrMockedUser) 

     valueEventListener.onDataChange(mockedDataSnapshot); 
     //valueEventListener.onCancelled(...); 

     return null; 
     } 
    }).when(mockedDatabaseReference).addListenerForSingleValueEvent(any(ValueEventListener.class)); 

    new LoginActivity().getSignedInUserProfile(); 

    // check preferences are updated 
    } 

} 

您需要添加相應的依賴關係,你模塊build.gradle

testCompile 'junit:junit:4.12' 
testCompile 'org.powermock:powermock:1.6.5' 
testCompile 'org.powermock:powermock-module-junit4:1.6.5' 
testCompile 'org.powermock:powermock-api-mockito:1.6.5' 
+0

我已經使用Robletric來測試我的其他方法,是否可以在一次測試中使用不同的測試編譯? – MeryT

+0

應該有可能。看到最後一個例子:https://github.com/robolectric/robolectric/wiki/Using-PowerMock –