1 00:00:00,390 --> 00:00:04,790 We just finished setting up our test, and now it's time for the moment of truth. 2 00:00:04,790 --> 00:00:08,950 Let's right-click anywhere inside our MainActivityTest class and 3 00:00:08,950 --> 00:00:11,820 choose Run to run our test. 4 00:00:12,980 --> 00:00:15,690 And as promised, we get an error. 5 00:00:16,700 --> 00:00:19,400 Specifically, we get a runtime exception. 6 00:00:19,400 --> 00:00:23,910 Method, get window, and Android.app.Activity not mocked. 7 00:00:25,560 --> 00:00:28,540 Sounds like we might need to do some mocking, but 8 00:00:28,540 --> 00:00:32,200 before we get ahead of ourselves let's click on the provided link for details. 9 00:00:36,470 --> 00:00:39,800 At the bottom is a section called "method not mocked". 10 00:00:39,800 --> 00:00:40,300 Let's read that. 11 00:00:41,378 --> 00:00:46,070 The Android jar file that is used to run unit tests does not contain 12 00:00:46,070 --> 00:00:47,610 any actual code. 13 00:00:49,110 --> 00:00:54,580 The code is provided by the Android system image on real devices. 14 00:00:54,580 --> 00:00:58,910 Instead all methods throw exceptions by default. 15 00:00:58,910 --> 00:01:02,740 This is to make sure that your unit tests only test your code and 16 00:01:02,740 --> 00:01:06,980 do not depend on any particular behavior of the Android platform 17 00:01:06,980 --> 00:01:09,471 that we haven't explicitly marked with Mockito or something. 18 00:01:10,750 --> 00:01:14,380 If that proves problematic, we can add the snippet below for 19 00:01:14,380 --> 00:01:16,650 to build our grade file to change this behavior. 20 00:01:18,270 --> 00:01:22,070 So it sounds like the reason this is not going to work is because the Android.jar 21 00:01:22,070 --> 00:01:24,650 file does not have any code. 22 00:01:24,650 --> 00:01:25,810 And by default, 23 00:01:25,810 --> 00:01:29,350 when we are unit testing, all Android methods will throw an exception. 24 00:01:30,690 --> 00:01:33,940 But if we would like them to instead return their default values, 25 00:01:33,940 --> 00:01:37,000 we can add the provided code snippet to or build.gradle file. 26 00:01:38,230 --> 00:01:41,660 Let's do that so we can dig a little bit deeper into what's going on. 27 00:01:42,820 --> 00:01:47,535 Let's copy the testOptions block and then paste it into 28 00:01:47,535 --> 00:01:52,359 our app's build.gradle file inside the Android tags. 29 00:01:56,799 --> 00:01:58,439 Then let's sync the project. 30 00:02:01,240 --> 00:02:06,704 And try running it again And 31 00:02:06,704 --> 00:02:10,320 now we get a null pointer exception, but what was a null? 32 00:02:11,520 --> 00:02:13,690 Let's start walking through the stack trace to find out. 33 00:02:15,730 --> 00:02:17,400 We start in the setUp method for 34 00:02:17,400 --> 00:02:20,996 our test With a call to our activities on create method. 35 00:02:20,996 --> 00:02:25,380 Then we call super.oncreate and 36 00:02:25,380 --> 00:02:30,300 main activity which calls the oncreate method and AppCompat activity. 37 00:02:33,030 --> 00:02:36,890 When then calls get delegate, also an AppCompat activity, 38 00:02:37,960 --> 00:02:43,970 which calls This create method, from the AppCompatDelegate class, 39 00:02:43,970 --> 00:02:47,450 followed by this create method which is right below the other one. 40 00:02:49,740 --> 00:02:53,860 And this create method creates a new AppCompatDelegateImplV7 41 00:02:55,260 --> 00:03:00,750 object, which is really just a call to super. 42 00:03:01,880 --> 00:03:05,980 Which brings us to our final resting place inside the constructor 43 00:03:05,980 --> 00:03:08,765 of App.CompatDelegateImplbase. 44 00:03:10,080 --> 00:03:10,580 Whew! 45 00:03:12,220 --> 00:03:16,310 So, something on this line is causing our no pointer exception, 46 00:03:17,430 --> 00:03:20,190 which means It's this mWindow variable. 47 00:03:21,380 --> 00:03:23,760 But then why is mWindow know null? 48 00:03:25,450 --> 00:03:30,200 Well it looks like mWindow is getting its value from the window parameter. 49 00:03:32,040 --> 00:03:35,820 So, let's step back through the stack to see where this value comes from. 50 00:03:37,420 --> 00:03:38,990 Window Window. 51 00:03:41,030 --> 00:03:41,780 Step up one. 52 00:03:42,890 --> 00:03:45,690 Window, window, step up again, 53 00:03:47,880 --> 00:03:52,320 window, that's also a parameter. 54 00:03:53,930 --> 00:03:58,180 Here we go, activity.getWindow. 55 00:03:58,180 --> 00:04:00,070 Let's right-click on this method and 56 00:04:00,070 --> 00:04:05,400 choose Go To > Declaration, to see where we're getting our window from. 57 00:04:07,670 --> 00:04:08,815 Well, that's boring. 58 00:04:08,815 --> 00:04:14,850 Activity.getWindow just returns a field mWindow. 59 00:04:14,850 --> 00:04:19,630 So now our question is, why is mWindow null? 60 00:04:19,630 --> 00:04:23,593 Let's search for mWindow = and 61 00:04:23,593 --> 00:04:32,270 there's only one match: "mWindow= new PhoneWindow(this)". 62 00:04:32,270 --> 00:04:34,910 So since mWindow is null, 63 00:04:34,910 --> 00:04:40,160 we can feel pretty confident that this attach method was never called. 64 00:04:41,580 --> 00:04:44,900 In fact as we can see by the comment up here, 65 00:04:46,790 --> 00:04:50,510 this attach method is part of android's internal API. 66 00:04:51,810 --> 00:04:54,600 Also what's up with all the errors? 67 00:04:54,600 --> 00:04:56,710 And where does this file come from anyway? 68 00:04:57,930 --> 00:04:59,780 Well, This file, 69 00:04:59,780 --> 00:05:04,200 along with most of the Android files we've been using, come from the Android SDK. 70 00:05:04,200 --> 00:05:05,720 Let me show you. 71 00:05:06,990 --> 00:05:15,920 If we click up here, to open the SDK Manager, we can see the path to our SDK. 72 00:05:17,620 --> 00:05:19,700 Then, if we navigate to that path 73 00:05:26,699 --> 00:05:28,283 Go into platforms and 74 00:05:28,283 --> 00:05:32,950 then pick the version of Android we're targeting 23 for me. 75 00:05:34,510 --> 00:05:36,942 We can see the android.jar file. 76 00:05:36,942 --> 00:05:39,560 This android.jar file 77 00:05:39,560 --> 00:05:44,860 provides us with all the Android framework classes we need to write our apps. 78 00:05:44,860 --> 00:05:48,260 But that doesn't mean it contains the complete framework. 79 00:05:48,260 --> 00:05:53,740 In fact, none of Android's internal API is included in this jar, 80 00:05:53,740 --> 00:05:55,350 which is why we have so many errors. 81 00:05:56,610 --> 00:06:01,040 Basically, there are two different versions of the Android.jar file. 82 00:06:01,040 --> 00:06:03,780 There's the version we used to develop with and 83 00:06:03,780 --> 00:06:06,580 there's the version that exists on a device. 84 00:06:06,580 --> 00:06:10,770 The version we used for development contains all the code we need to write 85 00:06:10,770 --> 00:06:14,940 apps, but it doesn't include any of the framework code. 86 00:06:14,940 --> 00:06:17,510 And as we've seen the framework code is 87 00:06:17,510 --> 00:06:19,600 pretty important when it comes to creating an activity. 88 00:06:19,600 --> 00:06:24,340 This is what makes unit testing on Android so difficult. 89 00:06:24,340 --> 00:06:27,500 The internal APIs, which are responsible for creating and 90 00:06:27,500 --> 00:06:31,710 launching activities, are only available on a device and 91 00:06:31,710 --> 00:06:35,020 if we're using a device, it's not a unit test. 92 00:06:35,020 --> 00:06:37,460 In the next video, we'll see how we can fix this and 93 00:06:37,460 --> 00:06:39,510 start exploring some other options for testing.