@untymage it's not working, because it's not even hitting your controller method. You can verify that by adding $this->withoutExceptionHandling(); to the top of your test, you should get No query results for model [Mockery_2_App_Thread] error.
Then if you make your spy partial ($this->spy(Thread::class)->makePartial()) you will get to the other error: General error: 1 no such table: mockery_2__app__threads
You haven't specified your table name so Laravel is trying to spell it from your class name which is Mockery_2_App_Threads in this case. All you need to do is to add table property to your model class:
protected $table = 'threads';
Now you will get to another error: Received Mockery_2_App_Thread::__construct(), but no expectations were specified. This is because Laravel is trying to create a new instance of the model class for the fetched thread, but it's failing because Thread class is mocked and no expectation are specified.
You can just mock the newInstance method to just return the spy: $spy->shouldReceive('newInstance')->andReturn($spy);.
Your final test should look like this and it should pass now:
factory(Thread::class)->create();
$spy = $this->spy(Thread::class)->makePartial();
$spy->shouldReceive('newInstance')->andReturn($spy);
$this->getJson("api/thread/1");
$spy->shouldHaveReceived('someCheck');
$spy->shouldHaveReceived('myMethod');