My goal is to run a suite of Espresso UI Tests, and have the Retrofit instance that has been created in the onCreate
method of my MainActivity reconfigured to return mocked JSON responses from localhost
, so I can test how the app's UI responds to response codes and different JSON data, etc.
So far, I've tried to drop in the MockWebServer
package, and I was able to get that up and running on a localhost server. However, the Retrofit instance was still configured to the production url.
I've tried passing arguments at the launch of a test, including manually setting the intent for the MainActivity with some extras
, in an attempt to set a flag that could toggle the string used for the Retrofit instance. However, it seems that the any arguments set in @Before
of a test don't get picked up at the launch of the MainActivity.
I've looked at these answers, but there doesn't appear to be a solution:
Android Espresso UI Test with mocked Retrofit API
Mock server requests Android Espresso UI Testing
This is my latest experiment:
@get:Rule
var activityRule = ActivityTestRule(MainActivity::class.java, true, false)
@Before
fun setup() {
}
@Test
fun intent() {
val intent = Intent()
activityRule.launchActivity(intent.putExtra("UITesting", true))
println(activityRule.activity.intent.extras)
}
Here is the Retrofit instance:
var BASE_URL = "https://api.invoicehome.com"
class NetworkManager {
private val service : networkService
// initialization with BASE_URL, using Gson converter factory to decode ( i believe there are other options available as well)
init {
val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
service = retrofit.create(networkService::class.java)
// }
}
}
Beginning of MainActivity, where there's an instance of the NetworkManager
:
class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {
private var networkManager = NetworkManager()
}
I would like something that could simply wrap around the instance of Retrofit, and pop in a URL, but I'm 99% sure this isn't realistic. If any swift devs are looking at this, I'm looking for analogous functionality to Swifter
.
So, can I somehow make the URL conditional for the Retrofit instance? Where would I pass in these flags? Is there a library that I'm missing that can do all of this for me?
You can use the help of MockWebServer library
You will need to abstract your NetworkManager
class and make two different implementations, one for mocking the requests and the other for making real requests and provide this as a dependency to your activity.
So for example:
NetworkManager Interface
interface NetworkManager {
fun doRequest()
}
Mock implementation
class MockedNetworkManager : NetworkManager {
override fun doRequest() {
// Mock request
}
}
Real implementation
class RealNetworkManager : NetworkManager {
override fun doRequest() {
// Real request
}
}
And your MainActivity should look something like this
class MainActivity : AppCompatActivity() {
private lateinit var networkManager: NetworkManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val shouldMock = intent.getBooleanExtra("UITesting", false)
if (shouldMock) {
networkManager = MockedNetworkManager()
} else {
networkManager = RealNetworkManager()
}
}
}