You've asked a huge question here. But I'll try to answer without writing an epic story. Your first question is easiest to deal with.
1. It should be possible on your phone to switch off 4G. I thought all phones could do that. What are you using?
2. There are a number of tools and techniques we can use to unit test our code. This whole area is huge and I could spend all day discussing it. There are different levels of testing, depending on what you want to test. You've mentioned Espresso, which is aimed at testing from the GUI point of view. Historically GUI testing has been difficult, because it's quite hard to mimic the actions of a user, and cope with the dynamic nature of a user interface. But what Espresso is giving you, is a way to automate what a user of your app is doing - button taps, navigation, input, etc.
And we can also look at unit testing other parts of your code, which don't involve the UI. Such as the database, or utility classes. Here we can use techniques like stubbing and mocking. Say for example, I'm writing a utility class, which returns some information from the database. You're writing another part of the system, which will use this class. You may want to test your part of the system, but I haven't finished my stuff yet. You need a way of mimicking my code. This is where stubs come in. A stub is just a simple dummy method, standing in for the real code. It usually returns no data, or canned data. It's not the real code. A mock takes this a step further, because it mimics the behaviour of the code, and returns data usually dependant on the input provided, so it has a bit more logic inside, making decisions. But both these techniques are doing basically the same thing - providing a way of substituting real code with a simulation of it. The point is, you are aiming to test the code which calls the mock/stub, and allow it to continue, even though some of the real code isn't there.
Another thing to consider is what part of your system you should be testing. Software systems usually have a lot of boiler plate code, or methods which you don't really need to test e.g. getter and setter methods. Things like this are trivial, and don't really need testing. Target those parts of your system which really need to be tested. People tend to look at what classes have been defined, and pick out certain crucial methods.
Another testing strategy is to define user scenarios. Construct your test cases according to how users will interact with your app. This is another big area of testing called 'BDD' (Behaviour driven development). There are testing tools which allow you to express your test cases in plain English. This makes them very readable, even for non technical people. The descriptions are then mapped on to low level tests by the testing tool. An example of such a tool is 'Cucumber'. But I don't know what the equivalent is for Android.
And before you even get to the activity of testing, there's a lot you can do to design your code in such a way that it can be tested easily. But I won't get into that, or I really would be here all day
As I said, various tools exist to help us with unit testing. As a starting point, look at:-
JUnit
Mockito
Espresso
There some basic information on the subject here
https://developer.android.com/training/testing/unit-testing/local-unit-tests
Unit testing of code is a hugely neglected area of software development, even by professionals. So it's great that you're considering how to do it properly. It really is the only way to ensure high quality code. Ultimately you want to be developing a suite of automatic regression tests - so whenever you change something in the code, your tests will run, and give you high confidence that you haven't broken anything. Regression tests are really important in big software systems, which have a lot of features.
There are a lot of web resources on the subject of unit testing, but hopefully this has given you some flavour of the things to consider.